说明:本文仅供学习交流,转载请标明出处,欢迎转载!
题目:输入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》
时间: 2024-10-05 21:57:18