题目讲解
数组中的第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);
}
};