题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
关键:引用!!!!!!!!!!!!!!
方法一:快排思想,时间复杂度O(n),修改了数组(改进的快排无法通过???疑惑——因为是用low做枢轴,所以必须先high--,从右边开始移动指针!!!!!!!!!!!!!!)
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> ans;
if(input.size()==0||k<=0 ||input.size()<k) return ans;
int start=0,end=input.size()-1;
int index=Partion(input,start,end);
while(index!=k-1)
{
if(index>k-1)
{
end=index-1;
index=Partion(input,start,end);
}
else
{
start=index+1;
index=Partion(input,start,end);
}
}
for(int i=0;i<k;i++)
ans.push_back(input[i]);//改变了输入的数组,时间复杂度O(n),运用了快排的思想
return ans;
}
int Partion(vector<int> &input,int low,int high)//引用很关键!!!!!!!
{
//if(input.empty() || low>high) return -1;
int pivot=input[high];
int i=low-1;
for(int j=low;j<high;j++)
{
if(input[j]<=pivot)
{
i++;
if(i!=j)
swap(input[i],input[j]);
}
}
swap(input[high],input[i+1]);
return i+1;
}
int Partion1(vector<int> &input,int low,int high)
{
int pivot=input[low];
while(low<high)
{
while(low<high && input[high]>=pivot)
high--;
input[low]=input[high];
while(low<high && input[low]<=pivot)
low++;
input[high]=input[low];
}
input[low]=pivot;
return low;
}
};
方法二:堆排序,时间复杂度O(nlogk),没有修改数组,适合海量数据
大顶堆,适用于升序;小顶堆,适用于降序
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> ans;
if(input.size()==0||k<=0 ||input.size()<k) return ans;
//初始化堆,i从最后一个父节点开始调整,满足大顶堆条件(注:为什么用k来代替input.size()?因为假设有海量数据,调整整个堆太复杂)
for(int i=k/2-1;i>=0;i--)
{
adjustHeap(input,i,i+k);
}
//从第k个元素开始分别与最大堆的最大值做比较,如果比最大值小,则替换并调整堆。
//最终堆里的就是最小的K个数。
for(int i=k;i<input.size();i++)
{
if(input[i]<input[0])
{
swap(input[i],input[0]);//堆首(最大值)和堆尾互换
adjustHeap(input,0,k-1);//k个数的剩余部分继续调整成大顶堆
}
}
for(int i=0;i<k;i++)
ans.push_back(input[i]);
return ans;
}
void adjustHeap(vector<int> &input, int start,int end)//调整堆(大顶堆)
{
int dad=start;
int son=dad*2+1;
while(son<=end)
{
if(son+1<=end && input[son]<input[son+1])
son=son+1;
if(input[dad]>input[son])
return;
else
{
swap(input[dad],input[son]);
dad=son;
son=2*dad+1;
}
}
}
};
方法三:堆排序,运用STL标准库函数heap(其实不属于标准库,调用需要#include<algorithm>),没有修改数组,适合海量数据
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> result;
if(input.size()==0||k<=0 ||input.size()<k) return result;
for(int i=0;i<k;i++)
result.push_back(input[i]);
make_heap(result.begin(),result.end());
for(int i=k;i<input.size();i++)
{
if(input[i]<result[0])
{
pop_heap(result.begin(),result.end());//弹出heap顶元素
result.pop_back();
result.push_back(input[i]);
push_heap(result.begin(),result.end());
}
}
sort_heap(result.begin(),result.end());
return result;
}
};
方法四:红黑树,运用STL标准库函数multiset结构
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> result;
if(input.size()==0||k<=0 ||input.size()<k) return result;
multiset<int,greater<int>> ans;//找到set中的最大值,即由大到小排序
for(auto it=input.begin();it!=input.end();it++)
{
if(ans.size()<k)//set里个数不足k,直接插入数据
{
ans.insert(*it);
}
else
{
auto max=ans.begin();//set里降序排列,取最大值
if( *it < *(ans.begin()) )
{
ans.erase(max);
ans.insert(*it);
}
}
}
for(auto it=ans.begin();it!=ans.end();it++)
{
result.push_back(*it);
}
return result;
}
};