先用数组前k个元素维护一个大小为k的大顶堆(每次将元素插在最后,然后自底向上调整),从第k+1个数组元素开始,当数组元素小于堆顶时,取出堆顶,然后将这个元素放在堆顶,自顶向下调整。
最后取出k个数的时候,先取出堆顶,然后将最后一个元素放在堆顶,自顶向下调整。
取出来的时候是从大到小的,所以最后还要对数组进行逆序。
class Solution {
public:
static const int maxn=1000000;
int f=200000000;
int a[maxn];
int nextp=1;
vector<int>ans;
void adjust(int idx){ //自底向上调整
while(idx>1){
if(a[idx]>a[idx/2]){
swap(a[idx],a[idx/2]);
idx=idx/2;
}
else
break;
}
}
void insert(int num,int k){
if(nextp-1<k){
a[nextp]=num;
adjust(nextp);
}
nextp++;
}
void del(int num){ //替换堆顶,然后自顶向下调整
a[1]=num;
int cur=1;
int left=cur*2;
int right=cur*2+1;
while(left<=nextp-1){
int maxidx=left;
if(right<=nextp-1&&a[left]<a[right])
maxidx=right;
if(a[cur]<a[maxidx]){
swap(a[cur],a[maxidx]);
cur=maxidx;
left=cur*2;
right=cur*2+1;
}
else
break;
}
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
if(k>input.size())
return {};
//fill(a,a+maxn,f);
for(int i=0;i<k;i++){
insert(input[i],k);
}
for(int i=k;i<input.size();i++){
int top=a[1];
if(input[i]<top){
del(input[i]);
}
}
for(int i=0;i<k;i++){
ans.push_back(a[1]);
int num=a[nextp-1];
nextp--;
del(num);
}
reverse(ans.begin(),ans.end());
return ans;
}
};