题目描述:
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
设计思想一:
创建一个结果容器,若放源数据的容器的源数据的个数少于k个,则把所有源数据直接插入结果容器,若源容器的数据数目多于k个,则取完k个后,以后取出的每个元素都要和结果容器的元素最大值比,若比结果容器的最大值大,则该元素替换结果容器的最大值,否则,取源容器的下一个数据。
因此容器元素数目够k个后,做三件事:1.在k个数里找最大数。2.删除原最大数。3.将新元素插入结果容器。
可在O(logk)时间内完成这三件。又由于有n个源数据,所以总的时间复杂度O(nlogk)
此法优势在于不修改输入数组,适合处理大量数据
class Solution {
public:
multiset<int,greater<int> > LeastNums;
multiset<int,greater<int> >::iterator it;
void GetLeastNums(vector<int> input,int k)
{
int i=0;
for(i=0;i<k;++i)
LeastNums.insert(input[i]);
int length=input.size();
if(length>k)
{
while(i!=length)
{
if(input[i]<*(LeastNums.begin()))
{
LeastNums.erase(LeastNums.begin());
LeastNums.insert(input[i]);
}
++i;
}
}
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
{
if(input.size()<k)
return {};
vector<int> Vec;
GetLeastNums(input,k);
for(it=LeastNums.begin();it!=LeastNums.end();++it)
{
Vec.push_back(*it);
}
return Vec;
}
};
设计思想二:
从面试题39“数组中出现次数超过一半的数字”取得启发,此题也用Partition()。能否调整到:某数左边是比它小的k-1个数,该数右边的数比它都大?时间复杂度是O(n)
这种方法需要修改输入数组,如果面试官要求不能修改输入数组,则不能用此法
#include <algorithm>
#define random(a,b) (rand()%(b-a+1)+a)
class Solution {
public:
int Partition(vector<int>& data, int length, int start, int end)
//vector<int>& data必须加引用,因为后期用的就是在Partition函数中改变的容器data
{
int pivot = random(start, end);
swap(data[pivot], data[end]);
int small = start - 1;
for (int index = start; index<end; index++)
{
//如果index所指向的元素小于pivot枢纽元素的话,index和small游标一起向右走,当index所指向的元素大于或者等于pivot枢纽元素的话,只是index自己向右走,small不动,这样的话index走啊走啊 发现有一个小于pivot枢纽元素的时候,将此元素与small所指向的元素互换
if (data[index]<data[end])//此处若改成大于号则从大到小排
{
++small;
if (small != index)
{
swap(data[index], data[small]);
}
}
}
++small;
//最后把small所指向元素与枢纽元素pivot互换
swap(data[small], data[end]);
return small;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
{
vector<int> output;
int n=input.size();
if(n==0||k<=0||k>n)
return {};
int start = 0;
int end = n - 1;
int index = Partition(input, n, start, end);
while(index != k - 1)
{
if(index > k - 1)
{
end = index - 1;
index = Partition(input, n, start, end);
}
else
{
start = index + 1;
index = Partition(input, n, start, end);
}
}
for(int i=0;i<k;++i)
output.push_back(input[i]);
return output;
}
};
扫描二维码关注公众号,回复:
2580145 查看本文章