方法一:利用快排的思想,循环找到第k个位置安放正确的元素,此时k的左边是小于k位置元素的元素,右边是大于k位置元素的元素,即前k个元素就是问题答案。时间复杂度O(n)。
int Partition(vector<int> &res,int s,int e)
{
int tp=res[s];
while(s<e)
{
while(s<e&&res[e]>=tp)e--;
res[s]=res[e];
while(s<e&&res[s]<=tp)s++;
res[e]=res[s];
}
res[s]=tp;
return s;
}
void GetKNumbers(vector<int> res,int k)
{
int s=0,e=res.size()-1;
int index=Partition(res,s,e);
while(index!=k-1) //当k位置安放正确的时候,前k个元素就是最终结果
{
if(index>k-1)e=index-1;
else s=index+1;
index=Partition(res,s,e);
}
for(int i=0;i<k;i++)
cout<<res[i]<<" ";
}
方法二:利用堆排序的思想,若找前k小的元素,则构建大顶堆,先将前k个元素构建成大顶堆,然后判断堆顶元素和第k+i元素,若堆顶元素大则将第k+i位置的元素交换,然后重新调整大顶堆,最后得到的大顶堆就是结果。时间复杂度O(nlogk);
void HeapAdjust(vector<int>&heap,int index)
{
int tp=heap[index];
for(int i=2*index+1;i<heap.size();i*=2)
{
if(i<heap.size()-1&&heap[i]<heap[i+1])
i++;
if(tp>heap[i])break;
heap[index]=heap[i];
index=i;
}
heap[index]=tp;
}
void GetKNumbers(vector<int> res,int k)
{
if(res.size()==0||res.size()<=k||k<=0)return;
vector<int> heap(k);//初始化k大小的堆
for(int i=0;i<k;i++)
heap[i]=res[i];//首先放入k个元素
for(int i=(k-1)/2;i>=0;--i)
HeapAdjust(heap,i);//初始化堆
for(int i=k;i<res.size();i++)
{//每次从原数组中拿出一个元素和当前堆顶值比较,
//然后判断是否可以放入,放入后继续调整堆结构
if(heap[0]>res[i]){
heap[0]=res[i];
HeapAdjust(heap,0);
}
}
for(int i=0;i<k;i++)
cout<<heap[i]<<" ";
}