原文地址:https://www.jianshu.com/p/cb3d31082bec
时间限制:1秒 空间限制:32768K
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
我的代码
class Solution {
public:
/*在非海量数据的情况下,Top-K问题的首推解法就是快排中的Partition算法。
不仅平均时间复杂度优越,可以达到O(n),并且相比于基于堆的算法
(包括:min_heapify、build_heap、insert等一系列过程),编码更简洁。
在海量数据的情况下,还是老老实实选择基于堆的这一数据结构的算法吧。
时间复杂度为O(nlogk)。并且大多数高级编程语言中都应该内置了基于堆的API,
所以编写起来也没有那么麻烦。
基于Partition算法:
选择一个Position(称为基准),基于该算法的Top-K算法,非常受Position好坏的影响,
所谓的坏,有可能使时间复杂度达到O(n*n)。
然后利用Partition算法进行划分,如果Partition得到的p小于K,则继续划分p的右边;
如果p大于K,则继续划分p的左边;如果p等于K,则算法结束。
这种算法的缺点是需要针对数据做频繁的移动操作,
如果数据量较大就需要使用文件的形式进行分治计算。*/
void swap(int& a,int& b){
int tmp=a;
a=b;
b=tmp;
}
int Partition(vector<int> &input, int s,int e, int k){
int base=input[s];
int i=s+1,j=e;
while(i<j){
while((i<=e)&&(input[i]<=base))
i++;
while((j>=0)&&(input[j]>=base))
j--;
if(i<j)
swap(input[i],input[j]);
}
swap(input[s],input[j]);
return j;
}
int GetKID(vector<int> &input, int s,int e, int k){
int p=Partition(input,s,e,k);
int num=p-s+1;
int id=-1;
if(num==k)
id=p;
else if(num>k)
id=GetKID(input,s,p-1,k);
else
id=GetKID(input,p+1,e,k-num);
return id;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> res;
int n=input.size();
if(n<1 || k<1 || n<k)
return res;
int id=GetKID(input,0,n-1,k);
for(int i=0;i<=id;i++)
res.push_back(input[i]);
return res;
}
};
运行时间:3ms
占用内存:472k
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> res;
int n=input.size();
if(n<1 || k<1 || n<k)
return res;
multiset<int,greater<int>> m;
multiset<int,greater<int>>::iterator itG;
multiset<int,greater<int>>::reverse_iterator ritG;
for(int i=0;i<n;i++){
if(m.size()<k)
m.insert(input[i]);
else{
itG=m.begin();
if(input[i]<*itG){
m.erase(itG);
m.insert(input[i]);
}
}
}
for(ritG=m.rbegin();ritG!=m.rend();ritG++)
res.push_back(*ritG);
return res;
}
};
运行时间:3ms
占用内存:476k