题目描述:
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
思路一:快速选择,时间效率O(n),但是会改变原来的数组
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> &input, int k) {
vector<int> res;
int n = input.size();
if (n == 0 || k>n)
return res;
partition(input, res, 0, n - 1, k);
return res;
}
void partition(vector<int> &input, vector<int> &res, int start, int end, int k) {
if (res.size() == k)
return;
//当数组大于5时用快速选择,否则插入排序
if (end - start + 1 > 3) {
int ref=median3(input,start,end);
int i = start, j = end - 1;
//分割
for (;;) {
while (input[i] <= ref) i++;
while (input[j] > ref) j--;
if (i < j) {
swap(input[i++], input[j--]);
}
else
break;
}
swap(input[i], input[end]);
if (i-start+1 <= k) {
for (int m = start;m <= i;m++)
res.push_back(input[m]);
if(i-start+1==k)
return;
else
partition(input, res, i + 1, end, k - (i -start+1));
}
else
partition(input, res, start, i, k);
}
//小数组用插入排序
else {
for (int i = start+1;i <=end;i++) {
int j;
int tmp = input[i];
for (j = i;j > start&&tmp<input[j-1];j--)
input[j] = input[j - 1];
input[j] = tmp;
}
int m = start;
while (k--) {
res.push_back(input[m++]);
}
}
}
//三数中值法求参考点
int median3(vector<int> &input,int start,int end){
int mid=(start+end)/2;
if(input[start]>input[mid])
swap(input[start],input[mid]);
if(input[end]<input[start])
swap(input[end],input[start]);
if(input[mid]>input[end])
swap(input[mid],input[end]);
//把参考点放到末尾
swap(input[mid],input[end]);
return input[end];
}
};
思路二:用堆排序,创建一个大小为k的数据容器存储最小的k个数字,接着读取n个数字,如果容器中的数字小于k个,则直接放入,如果已经满了,那么判断新来的数字和容器中最大数字的关系,如果大于则舍弃,如果小于则插入到容器中。直接实现堆排序太过复杂,但是可以用红黑树来替代,红黑树的查找、删除和插入操作都只需要O(logk)时间。所以用STL中的multiset(允许重复)来实现,放入时按从小到大排序。
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> res;
int n=input.size();
if(k>n)
return res;
multiset<int,greater<int>> arr;
for(int i=0;i<k;i++)
arr.insert(input[i]);
multiset<int>::iterator itr=arr.begin();
for(int i=k;i<n;i++){
if(input[i]<*itr){
arr.erase(itr);
arr.insert(input[i]);
itr=arr.begin();
}
}
for(;itr!=arr.end();++itr)
res.push_back(*itr);
return res;
}
};