给定整数数组 nums
和整数 k
,请返回数组中第 k
个最大的元素。
请注意,你需要找的是数组排序后的第 k
个最大的元素,而不是第 k
个不同的元素。
你必须设计并实现时间复杂度为 O(n)
的算法解决此问题。
使用堆排序的思想:
/**
堆排序推荐讲解视频:https://www.bilibili.com/video/BV1fp4y1D7cj/?spm_id_from=333.337.search-card.all.click&vd_source=302c1785738370607d43006bfc028aba
*/
class Solution {
public int findKthLargest(int[] nums, int k) {
// 从第一个非叶子节点开始够造大根堆(第i个节点的父节点下标为 (i-1)/2 )
int len = nums.length-1;
for(int i = (len-1)/2; i>=0; i--){
heapfiy(nums, nums.length, i);
}
// 然后交换堆顶元素和最后一个元素,继续维护堆性质
for(int i=0; i<k; i++){
swap(nums, 0, len-i);
heapfiy(nums, len-i, 0);
}
return nums[len-k+1];
}
// 要维护的大根堆数组, 维护的数组长度,维护哪一个位置下的大根堆
public void heapfiy(int[] arr, int len, int top){
if(top<0 || top>=len) return;
// 找到 i 位置处的 两个孩子节点的位置
int left = top*2+1;
int right = top*2+2;
// 找最大的元素位置
int largest = top;
if(left<len && arr[left] > arr[largest]) largest = left;
if(right<len && arr[right] > arr[largest]) largest = right;
// 最大值的位置不等于i,就需要交换位置
if(largest != top) {
swap(arr, top, largest);
// 因为largest位置处的值已经被i出值占用了,因此就可能导致largest为顶点的树不符合大根堆特性
heapfiy(arr, len, largest);
}
}
public void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}