输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
最优方法可以做到n*log(k)。做法就是使用堆排序,只维护一个规模为k的大根堆,之后遍历所有的数字,一旦后面数字比堆顶小,则交换两数,并重新调整大根堆,遍历完成后堆中元素就是最小的k个数(但是这K个数不一定是排序的)
代码如下:
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k){
int i,j=0;
vector<int> res;
int n=input.size();
if(n<k) return res; //如果K比总数还大,直接返回
maxheap(input,k); //由前K个数建立一个大根堆
for(i=k;i<n;i++){
if(input[0]>input[i]) swap(input[0],input[i]); //之后的数字只要比堆顶大,则改变堆顶,并调整K规模的大根堆
fixdown(input,0,k);
}
for(i=0;i<k;i++) res.push_back(input[i]); //遍历完成后,输出前K个即为最小的K个数
return res;
}
void maxheap(vector<int> &num,int n){
int i;
for(i=n/2-1;i>=0;i--){
fixdown(num,i,n-1);
}
}
void fixdown(vector<int> &num, int i,int n){ //这里的n是下标,所以之前的fixdown要是n-1
int j;
int flag=1;
while(2*i+1<n && flag){ //常规堆排序做法,不详述
if(2*i+2>=n) j=2*i+1;
else{
if(num[2*i+2]<num[2*i+1]) j=2*i+1;
else j=2*i+2;
}
if(num[i]<num[j]){
swap(num[i],num[j]);
i=j;
}
else flag=0;
}
}
};