题目:
给定整数数组 nums
和整数 k
,请返回数组中第 k
个最大的元素。
请注意,你需要找的是数组排序后的第 k
个最大的元素,而不是第 k
个不同的元素。
题解:
快排每轮partition就可以将选中的pivot放到其最终有序位置,当某轮pivot被放到第k大元素位置(从小到大有序序列的下标n-k处)时,确定该pivot为结果
pivot的选择利用随机数可以防止最差时间复杂度。
nextInt()用法:
会随机生成一个整数,这个整数的范围就是int类型的范围-2^31 ~ 2^31-1,但是如果在nextInt()括号中加入一个整数a那么,这个随机生成的随机数范围就变成[0,a)。
class Solution {
public int findKthLargest(int[] nums, int k) {
//第k大元素,即排序后下标为n-k的元素,使用partition方法确定下标n-k元素
int target = nums.length - k;
int from = 0, to = nums.length - 1;
while (true) {
int idx = partition(nums, from, to); //每次partition返回pivot插入的位置
if (idx == target) { //如果插入的位置是目标位置,找到第k大元素
return nums[target];
} else if (idx > target) { //如果插入的位置大于目标位置,目标位置搜索范围应该在idx左边
to = idx - 1;
} else { //如果插入的位置小于目标位置,目标位置搜索范围应该在idx右边
from = idx + 1;
}
}
}
Random rand = new Random();
//返回单次partition确定pivot元素固定到的位置
private int partition(int[] nums, int from, int to) {
int pivotIndex = rand.nextInt(to - from + 1) + from;
int pivot = nums[pivotIndex];
//随机pivot交换到头部
int temp = nums[from];
nums[from] = pivot;
nums[pivotIndex] = temp;
int left = from, right = to;
while (left < right) {
while (left < right && nums[right] >= pivot) { //从右往左找到第一个<pivot的
right--;
}
if (left < right) {
nums[left] = nums[right];
}
while (left < right && nums[left] <= pivot) { //从左往右找到第一个>pivot的
left++;
}
if (left < right) {
nums[right] = nums[left];
}
}
nums[left] = pivot; //最后把pivot放到left的位置
return left;
}
}
参考:力扣