题目描述(来自剑指offer)
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
方法一:
/*
红黑树:multiset集合 利用仿函数改变排序顺序 时间复杂度O(nlogk)
*/
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
int len=input.size();
if(len<=0||k>len) return vector<int>();
//仿函数中的greater<T>模板,从大到小排序
multiset<int, greater<int> > leastNums;
vector<int>::iterator vec_it=input.begin();
for(;vec_it!=input.end();vec_it++)
{
//将前k个元素插入集合
if(leastNums.size()<k)
leastNums.insert(*vec_it);
else
{
//第一个元素是最大值
multiset<int, greater<int> >::iterator greatest_it=leastNums.begin();
//如果后续元素<第一个元素,删除第一个,加入当前元素
if(*vec_it<*(leastNums.begin()))
{
leastNums.erase(greatest_it);
leastNums.insert(*vec_it);
}
}
}
return vector<int>(leastNums.begin(),leastNums.end());
}
};
方法二:利用vector sort
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> res;
if(input.empty()||k>input.size()) return res;
sort(input.begin(),input.end());
for(int i=0;i<k;i++)
res.push_back(input[i]);
return res;
}
};
方法三:
/*
*基于堆排序算法,构建最大堆。时间复杂度为O(nlogk)
*如果用快速排序,时间复杂度为O(nlogn);
*如果用冒泡排序,时间复杂度为O(n*k)
*/
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> result;
if(input.size()==0||k==0||k>input.size()){
return result;
}
for(int i=input.size()/2-1;i>=0;i--){//初始化堆
adjustHeap(input,i,k);
}
int i=k;
while(i<input.size()){
if(input[0]>input[i]){
int temp=input[i];
input[i]=input[0];
input[0]=temp;
adjustHeap(input,0,k);
i=k;
}else {
i++;
}
}
for(int i=0;i<k;i++){
result.push_back(input[i]);
}
return result;
}
void adjustHeap(vector<int>&input,int i,int length){//堆调整
int child=i*2+1;
if(child<length){
if(child+1<length&&input[child+1]>input[child]){
child=child+1;
}
if(input[child]>input[i]){
int temp=input[i];
input[i]=input[child];
input[child]=temp;
adjustHeap(input,child,length);
}
}
}
void heapSort(vector<int>&input,int length){//堆排序
for(int i=length/2-1;i>=0;i--){//初始化堆
adjustHeap(input,i,length);
}
for(int i=length-1;i>0;i--){
int temp=input[i];
input[i]=input[0];
input[0]=temp;
adjustHeap(input,0,i);
}
}
};
public:
//快排递归核心算法---基准数左边序列都比基准数小,右边序列都比基准数大
int Partition(vector<int> & a,int left,int right)
{
if(left > right)
return -1;
int i,j,t,temp;
temp = a[left]; //temp是一趟排序的基准数
i=left;j=right;
while(i != j)
{
//顺序很重要,要先从右往左找比基准数小的
while(a[j] >= temp && i<j)
j--;
//再从左往右找比基准数大的
while(a[i] <= temp && i<j)
i++;
if(i < j) //当哨兵i和哨兵j没有相遇,则交换
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
//当i=j时,基准数归位
a[left] = a[i];
a[i] = temp;
return i; //在a[i]左边的序列均比a[i]小
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> output;
int len = input.size();
if(input.empty() || k>len)
return output;
//对容器进行快排过程,直到基准数左边的序列个数达到k个
int index = Partition(input,0,len-1);
while(index != k-1)
{
if(index < k-1) //递归右序列
{
index = Partition(input,index+1,len-1);
}
else //递归左序列
{
index = Partition(input,0,index-1);
}
}
for(int i=0;i<k;i++)
output.push_back(input[i]);
return output;
}
};