直接思路:
- 排序后求第K大
- 优先队列遍历数组,保持Size<=k,队列peek()为K大元素。
快排优化:
优化1:
快速排序不必排完全部,每次partition可以确认其中一个pivot的位置,pivot位置落在第K个的索引即可。
这里注意手写快排原地操作的写法。最左的位置默认为pivot,所以遍历先从left+1开始遍历。j为[left+1,right]中小于pivot的所有元素的最右侧的值。当遍历的时候出现比pivot小的数的时候,则把j++,然后把比pivot小的数放到j的位置。
public int partition(int[] nums, int left, int right){
int pivot = nums[left];
int j = left;
for(int i = left + 1; i <= right; i++){
if(nums[i] < pivot){
j++;
swap(nums, j, i);
}
}
swap(nums, left, j);
return j;
}
优化2:
pivot最好不要初始化为最左的值,防止最坏情况的发生应该随机化。
if (right > left) {
int randomIndex = left + 1 + random.nextInt(right - left);
swap(nums, left, randomIndex);
}
int pivot = nums[left];
优化3:
遍历可改为双指针