说明:本文仅供学习交流,转载请标明出处,欢迎转载!
题目:输入n个整数,找出其中最小的k个数。
《剑指offer》给出了两种实现算法:
算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合。算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值。
算法2:采用top-k算法。如果要找最小的K个数,我们才用一个含有K个值的大顶堆;如果要找最大的K个数,我们采用小顶堆。该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序。
这里我说明下《剑指offer》在实现上我认为不足的地方:书中用一个基于红黑树的multiset容器来模拟堆,但实际上红黑树是一棵BST,而堆不一定满足BST的特征。虽然用红黑树能得到结果,但是我认为并不是最好的,其实STL中有一个容器适配器priority_queue,其底层的实现数据结构就是一个堆,由于堆是一棵完全二叉树,所以数组的下标与标准定义的左右孩子相对应,所以用基于vector容器的priority_queue的大顶堆我们能够获取最小的K个数。
我的实现代码(用priority_queue):
int* GetMinK(int *arr,int n,int k,int *Result)//用priority_queue实现一个堆
{
if(!arr || n<1 || k<1 || k>n || !Result)
return NULL;
priority_queue<int,vector<int>,less<int> > q;//建一个大顶堆(less),小顶堆(greater)
int i;
for(i=0;i<k;i++)//先压入k个元素
{
q.push(arr[i]);
}
int max=q.top();//获取堆顶元素
for(i=k;i<n;i++)
{
if(arr[i]<max)//如果当前元素比堆顶元素还小
{
q.pop();//将堆顶元素删除
q.push(arr[i]);//并将当前元素压入到堆中
max=q.top();//更新max值(栈顶元素值)
}
}
i=0;
while(!q.empty())//将堆中每一个元素的值从堆中弹出,并放入到输出数组中
{
Result[i++]=q.top();
q.pop();
}
return Result;
}
《剑指offer》中用multiset容器实现的代码:
#include<iostream>
#include<set>//用到deque容器
#include<iterator>//用到输出迭代器
#include<algorithm>//用到copy函数
#include<functional>//用到仿函数
using namespace std;
int* GetMinK(int *arr,int n,int k,int *Result)//用红黑树实现
{
if(!arr || n<1 || k<1 || k>n || !Result)
{
cout<<"Invalid Input!";
return NULL;
}
multiset<int,greater<int> >mset(arr,arr+k);//用降序排序
int i=k;
multiset<int,greater<int> >::iterator iter;
for(;i<n;i++)
{
iter=mset.begin();
if(arr[i]<*iter)//如果当前元素小于map中的最大值
{
mset.erase(iter);
mset.insert(arr[i]);
}
}
i=0;
while(!mset.empty())//将集合中的元素复制到输出数组中后删除
{
iter=mset.begin();
Result[i++]=*iter;
mset.erase(iter);
}
return Result;
}
测试代码:
int main()
{
int arr[]={1,9,4,3,2,5,6,7,8};
int n=sizeof(arr)/sizeof(int);
cout<<"原数组的元素为:";
copy(arr,arr+n,ostream_iterator<int>(cout," "));
cout<<endl;
cout<<"请输入k值:";
int k;
while(cin>>k)
{
int *result=new int[k];
result=GetMinK(arr,n,k,result);
if(result)
{
copy(result,result+k,ostream_iterator<int>(cout," "));
}
cout<<endl;
delete []result;
}
return 0;
}
测试结果如下:
参考文献------------《剑指offer》