在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
题解思路
每次切分操作总能排定一个元素,还能够知道这个元素它最终所在的位置,这样每经过一次 partition(切分)操作就能缩小搜索的范围
实现代码
public class Solution {
public int findKthLargest(int[] nums, int k) {
int len = nums.length;
int left = 0;
int right = len - 1;
// 转换一下,第 k 大元素的索引是 len - k
int target = len - k;
while (true) {
int index = useSort(nums, left, right);
if (index == target) {
return nums[index];
} else if (index < target) {
left = index + 1;
} else if (index > target) {
right = index - 1;
}
}
}
/**
* 在数组 nums 的子区间 [left, right] 执行 partition 操作,返回 nums[left] 排序以后应该在的位置
* 在遍历过程中保持循环不变量的语义
* 1、[left + 1, i] < nums[left]
* 2、(i, j] >= nums[left]
*/
private int useSort(int[] nums, int left, int right) {
int base = nums[left];
int i = left;
for (int j = left + 1; j <= right; j++) {
// 小于 pivot 的元素都被交换到前面
if (nums[j] < base) {
i++;
swap(nums, i, j);
}
}
swap(nums, i, left);
return i;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}