题目讲解
数组中的第K个最大元素
算法讲解
堆排序:1. 寻找最后一个节点的父亲,依次向上遍历,完成小堆的建立;2. 从最后一个元素开始,和堆顶的数据做交换,此时最小的数据在对后面,然后对剩下的区间重新完善小堆
class Solution {
public:void AdJustDown(vector<int>& nums, int n, int parent){int child = parent* 2 + 1;while(child < n){//寻找小儿子if(child + 1 < n && nums[child] > nums[child + 1])child++;if(nums[child] < nums[parent]){swap(nums[child], nums[parent]);parent = child;child = parent * 2 + 1;}else break;}}int findKthLargest(vector<int>& nums, int k) {//建小堆int n = nums.size();for(int i = (n- 1 - 1) / 2; i >= 0; i--){AdJustDown(nums, n, i);}//开始堆排序 数组排降序int end = n - 1;while(end > 0){swap(nums[0], nums[end]);//剩下的区间完善小堆AdJustDown(nums, end, 0);end--;}return nums[k-1];}
};
快速选择算法:1.还是数组分三块,分成<key == key >key;2. 确定第k大在哪个区间,之后直接寻找这个区间的第k大即可
class Solution {
public:int my_qsort(vector<int>& nums, int l, int r, int k){//确定第k大的区域,后面的区域不需要考虑if(l == r)return nums[l];int i = l;int left = l - 1;int right = r + 1;int key = nums[rand() % (r - l + 1) + l];while(i < right){if(nums[i] < key)swap(nums[++left], nums[i++]);else if(nums[i] == key)i++;else swap(nums[--right], nums[i]);}//选择k出现的区域int c = r - right + 1;int b = right - left - 1;if(c >= k)return my_qsort(nums,right, r, k);else if(b + c >= k)return key;else return my_qsort(nums, l, left, k - b -c);}int findKthLargest(vector<int>& nums, int k) {//快速选择算法srand(time(NULL));int n = nums.size();return my_qsort(nums, 0, n-1, k);}
};