https://leetcode.com/problems/kth-largest-element-in-an-array/
解法一:将数组看为没有调整到位的最大堆,由于堆是完全二叉树,因此根节点与子节点的下标存在对应关系。
每次从堆中取出最大值,将其放至根节点,再与最后一个节点互换位置,然后将其从堆删除。
参考视频:https://www.bilibili.com/video/av47196993?from=search&seid=796459169887290526
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int tmp;
for(int i=0;i<k;i++){
tmp = heapify(nums);
}
return tmp;
}
void swap(vector<int>& a, int i, int j){
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
int heapify(vector<int>& a){//每次找出堆中最大值,将其移动至根节点,与最后一个节点互换后,将最大值从堆中删除
int n = a.size();
if(n==1) {
int tmp = a[0];
a.pop_back();
return tmp;
}
int last = n-1;
int parent;
for(parent = (last-1)/2; parent>-1; parent--){
int c1 = 2*parent+1;//堆是完全二叉树,所以父节点与子节点的数组下标存在固定关系
int c2 = 2*parent+2;
int maxi = parent;
if(c1<n && a[c1]>a[maxi])
maxi = c1;
if(c2<n && a[c2]>a[maxi])
maxi = c2;
if(parent!=maxi)
swap(a, parent, maxi);
}
int result = a[0];
a[0] = a[last];
a.pop_back();
return result;
}
};
解法二:采用快排中的partition算法,每次将首个元素记为p,将数组中大于p的放在它的左边,小于等于p的放在它右边。如果此时p的序号正好等于给定的k,则返回p;如果p的序号小于k,对p右侧的部分递归调用;如果p的序号大于k,对p左侧的部分递归调用。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int left = 0;
int right = nums.size()-1;
int tmp = partition(nums, left, right);
while(true){
if(tmp+1==k) return nums[tmp];
else if(tmp+1<k)
left = tmp+1;
else
right = tmp-1;
tmp = partition(nums, left, right);
}
}
int partition(vector<int>&a, int l, int r){
int p = a[l];
int i=l, j=r;
while(i<j){
while(i<j && a[j]<=p) j--;
if(i<j)
a[i++]=a[j];
while(i<j && a[i]>=p) i++;
if(i<j)
a[j--]=a[i];
}
if(i==j) a[i]=p;
return i;
}
};
欢迎关注公众号: