题目:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
分析:
方法(1):排序(升序),找前k个数据
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//在n个数中找最小的前k个数(排序)
vector<int> v;
if(k<=0 || input.size()<=0 || k>input.size())
return v;
sort(input.begin(), input.end());//默认是升序
int i=0;
while(i<k)
{
v.push_back(input[i]);
i++;
}
return v;
}
方法(2):用n个数据的前建k个元素的大堆,然后用剩下的元素与堆顶元素比较,比堆顶小的元素入堆,直到完,最后堆中保留的就是最小的前k个元素
//向下调整算法(建大堆)
void Adjustdown(vector<int>& a, int n, int parent)
{
int child=parent*2+1;//左孩子
while(child<n)
{
if(child+1<a.size() && a[child+1]>a[child])//保证a[child]是最大孩子
{
child++;
}
if(a[parent]<a[child])
{
swap(a[parent], a[child]);
parent=child;
child=parent*2+1;
}
else
{
break;
}
}
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//在n个数中找最小的前k个数(堆)
vector<int> v;
if(k<=0 || input.size()<=0 || k>input.size())
return v;
//先拿前k个数建一个大堆
//从最后一个节点的父亲开始调整
for(int i=(k-2)/2;i>=0;i--)
{
Adjustdown(input,k,i);
}
//将剩下的数据与堆顶数据比较,小于堆顶元素就入堆(替换堆顶,并且将堆顶向下调整)
for(int i=k;i<input.size();i++)
{
if(input[i]<input[0])
{
input[0]=input[i];
Adjustdown(input,k, 0);
}
}
//小堆中数据尾插到返回的vector中
for(int i=0;i<k;i++)
{
v.push_back(input[i]);
}
return v;
}
方法(3):使用优先级队列(要显式传greater仿函数,因为这才是升序,默认是降序的),将原来vector的数据依次push到这个优先级队列中,可以使得最后的元素按照升序排序,然后将前k个push到返回的vector中
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//在n个数中找最小的前k个数(排序)
vector<int> v;
if(k<=0 || input.size()<=0 || k>input.size())
return v;
priority_queue<int, vector<int>, greater<int>> q;//小堆
for(int i=0;i<input.size();i++)//建立优先级队列(升序排序)
{
q.push(input[i]);
}
while(k)
{
v.push_back(q.top());
q.pop();
k--;
}
return v;
}
方法(4):利用快排思想,找到一个基准值,使得它大于左边所有数,小于右边所有数,如果这个基准值的下标是k-1的话就说明找到了,否则反复找,直到知道为止
int partion(vector<int>& v, int begin, int end)
{
int key=v[begin];//保存v[begin]到变量key里
while(begin<end)
{
while(begin<end && v[end]>=key)
{
end--;
}
//来到这,说明v[end]<key
v[begin]=v[end];
while(begin<end && v[begin]<=key)
{
begin++;
}
//来到这说明v[behin]>key了
v[end]=v[begin];
}
//来到这v[begin]的是<key
v[begin]=key;
return begin;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//在n个数中找最小的前k个数(堆)
vector<int> v;
if(k<=0 || input.size()<=0 || k>input.size())
return v;
//调用partion函数看返回的pos是不是k-1(最小的前k个数据,下标是0,1...k-1)
int pos=partion(input, 0, input.size()-1);
while(pos!=k-1)
{
if(pos>k-1)//说明在左半面
{
pos=partion(input, 0, pos-1);
}
else
{
pos=partion(input, pos+1, input.size()-1);
}
}
//来到这说明pos==k-1了
vector<int> v1(input.begin(), input.begin()+k);
return v1;
}