top k 问题;
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
// 解法1 全排序 时间复杂度O(nlogn)
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> res;
if(input.empty()||k>input.size()) return res;
sort(input.begin(),input.end());
for(int i=0;i<k;i++)
res.push_back(input[i]);
return res;
}
};
解法2:最大堆
注意:当输出前几个小的数时维持最大堆,反之最小堆
//利用STL里面的multiset,维持一个集合
//set中按照仿函数中的greater<T>模板,从大到小排序
class Solution {
public:
// top k 问题 解2
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> res;
if(input.size() == 0 || input.size() < k)
return res;
set<int,greater<int> > intSet; // 维持一个最大堆
for(auto iter = input.begin();iter != input.end(); ++ iter){
if ((intSet.size()) < k)
intSet.insert(*iter);
else {
//第一个元素是最大值
auto itBegin = intSet.begin();
if (*(intSet.begin() ) > *iter ){
//先在set中删除后插入
intSet.erase(itBegin);
intSet.insert(*iter);
}
}
}
auto itBeg = intSet.begin();
//使其从小到大输出
for (int i = 0; i < k; i++){
res.push_back( *itBeg ++);
}
return res;
}
};
解法3:Partiton思想 时间复杂度O(n)
class Solution {
public:
int Partition(vector<int>& input, int begin, int end)
{
int low=begin;
int high=end - 1;
int pivot=input[end];
while(low<high)
{
while(low<high&&pivot<=input[high])
high--;
while(low<high&&pivot>=input[low])
low++;
if(low <= high){
swap(input[high],input[low]);
high --;
low ++;
} else
break;
}
swap(input[low],input[end]); // 注意交换的是low和end的值,不能是high
return low;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
int len=input.size();
if(len==0||k>len) return vector<int>();
if(len==k) return input;
int start=0;
int end=len-1;
int index=Partition(input,start,end);
while(index!=(k-1) && k >0) //注意判断k是否大于0,否则死循环
{
if(index>k-1)
index=Partition(input,start,index-1);
else
index=Partition(input,index+1,end);
}
vector<int> res(input.begin(), input.begin() + k);
return res;
}
};