数组第K大
看前面排序的序列:{26,53,48,15,13,48,32,15}
我们第一次选择了26为哨兵,进行一轮的排序过程为:
上面红框位置表示当前已经被赋值给了pivot或者其他位置,可以空出来放移动来的新元素了。我们可以看到26最终被放到了属于自己的位置上,不会再变化,而26的左右两侧可以分别再进行排序。
这里还有一个关键信息, 我们可以知道26的索引为3。根据元素总数来判断,递增排序之后26一定是第5大的元素 。这就是解决本问题的关键,既然知道26是第5大,那如果我要找第2大,一定是要到右边找。如果要找第6大,一定要到左边找(当然,如果降序排序就反过来了),而不需要的那部分就不用管了。这就是为什么能用快速排序解决这个问题。
public int findKthLargest(int[] nums, int k) {
int n = nums.length;
return quickselect(nums, 0, n - 1, n - k);
}
public int quickselect(int[] nums, int l, int r, int k) {
if (l == r) return nums[k];
int x = nums[l], i = l - 1, j = r + 1;
while (i < j) {
do i++; while (nums[i] < x);
do j--; while (nums[j] > x);
if (i < j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
if (k <= j) return quickselect(nums, l, j, k);
else return quickselect(nums, j + 1, r, k);
}