題目:輸入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;
}