给定整数数组 n u m s nums nums 和整数 k k k,请返回数组中第 k k k 个最大的元素。
请注意,你需要找的是数组排序后的第 k k k 个最大的元素,而不是第 k k k 个不同的元素。
你必须计划并实现时间复杂度为 O ( n ) O(n) O(n) 的算法办理此问题。
数据约束
1 ≤ k ≤ n u m s . l e n g t h ≤ 1 0 5 1 \le k \le nums.length \le 10 ^ 5 1≤k≤nums.length≤105
− 1 0 4 ≤ n u m s [ i ] ≤ 1 0 4 -10 ^ 4 \le nums \le 10 ^ 4 −104≤nums≤104
解题过程
经典求第 k k k大,最佳方案是用随机选择算法,时间复杂度大致是 O ( N ) O(N) O(N) 这个量级。
考虑到标题分类在堆,那除了调用 API 快速处理的方法之外,再写一下手撕堆看成练习。
干系详细的先容,可以参考 随机快排与随机选择 以及 堆排序与堆操作。
具体实现
使用堆 API
class Solution {
public int findKthLargest(int[] nums, int k) {
Queue<Integer> queue = new PriorityQueue<>();
for(int num : nums) {
queue.offer(num);
}
for(int i = 0; i < nums.length - k; i++) {
queue.poll();
}
return queue.peek();
}
}
复制代码
自己实现堆
class Solution {
public int findKthLargest(int[] nums, int k) {
int n = nums.length;
buildHeap(nums);
// 注意这里要修正索引
while(k - 1 > 0) {
swap(nums, 0, --n);
downAdjust(nums, 0, n);
k--;
}
return nums[0];
}
// 交换数组中的两个元素
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 由上而下调整元素
private void downAdjust(int[] arr, int cur, int size) {