算法之查找第k小的数和查找最小的k个元素
2013-05-22 14:01
246 查看
利用快速排序的思想查找第k小的数,主要的核心思想还是快速排序的分治算法,具体的思路是这样的:
1 利用快排的partion函数将数组分成左右两个部分,
2 如果p刚好等于k,则说明p位置的数,就是我们要找的数,如果分出来的边界位置p小于给定的数k,我们知道最小的第k个数,肯定在p的右边,如果p大于给定的k则在p边界的左边
3 递归在p的左边或者右边查找
注:p为数组下标需要加1,一般会使用随机数,即在数组中随机选取一个数作为每次分边界的值。
具体的细节可以查看《算法导论》第九章,下面是简单的实现代码,没有完全验证过;
查找最小的k个数,我用上面的方法肯定也是可以的,只需要将分界的p返回,p左边的数(包括p位置本身),就是我们需要的所有的最小的k个数,简单验证过,还可以维护一个集合数据的个数为k,每次从数组中取出一个数,如果集合中的数字的个数小于k,则认为集合中的所有数都是最小的k个数,如果集合中的的数据的个数大于k了,则每次将最大的数置换出来,遍历完数组之后,集合中的k个数就是最小的k个数的集合,用c++ 中的STL可以简单实现下面的代码:
1 利用快排的partion函数将数组分成左右两个部分,
2 如果p刚好等于k,则说明p位置的数,就是我们要找的数,如果分出来的边界位置p小于给定的数k,我们知道最小的第k个数,肯定在p的右边,如果p大于给定的k则在p边界的左边
3 递归在p的左边或者右边查找
注:p为数组下标需要加1,一般会使用随机数,即在数组中随机选取一个数作为每次分边界的值。
具体的细节可以查看《算法导论》第九章,下面是简单的实现代码,没有完全验证过;
/* 查找第k小的数 */ #include <iostream> using namespace std; int partion(int array[],int s,int e) { int temp = array[s]; while(s < e) { while(array[e] >= temp&& s<e ) e--; if(s < e) array[s] = array[e]; while(array[s] < temp && s<e) s++; if(s < e) array[e] = array[s]; } array[s] = temp; return s; } int search_k(int array[],int s,int e,int k) { int p = partion(array,s,e); int q = p+1; if( q == k ) return array[p]; if( q < k) return search_k(array,p+1,e,k); if( q > k) return search_k(array,s,p-1,k); } int main() { int array[1000]; int n; int k; while( cin >> n >> k && n!=0) { for(int i=0;i<n;i++) cin >> array[i]; cout << search_k(array,0,n-1,k) << endl; } }
查找最小的k个数,我用上面的方法肯定也是可以的,只需要将分界的p返回,p左边的数(包括p位置本身),就是我们需要的所有的最小的k个数,简单验证过,还可以维护一个集合数据的个数为k,每次从数组中取出一个数,如果集合中的数字的个数小于k,则认为集合中的所有数都是最小的k个数,如果集合中的的数据的个数大于k了,则每次将最大的数置换出来,遍历完数组之后,集合中的k个数就是最小的k个数的集合,用c++ 中的STL可以简单实现下面的代码:
#include <iostream> #include <set> #include <vector> using namespace std; typedef multiset<int,greater<int> > IntHeap; void FindLeastKNum(vector<int> &ivec, int k, IntHeap &leastNum) { for(vector<int>::iterator iter= ivec.begin(); iter != ivec.end(); iter++) { // cout << *iter << " "; if(leastNum.size() < k) leastNum.insert(*iter); else { IntHeap::iterator Tmpiter = leastNum.begin(); // // cout <<"the biggest"<< *Tmpiter <<endl; if(*iter < *Tmpiter) { leastNum.erase(Tmpiter); leastNum.insert( *iter ); } } } } int main() { int n; cin>> n ; vector<int> ivec; while(n--) { int num =0; cin >> num; ivec.insert(ivec.begin(),num); } int k; cin >> k; IntHeap leastNum; FindLeastKNum(ivec,k,leastNum); cout << "the least k nums are: " <<endl; for(IntHeap::iterator iter=leastNum.begin(); iter != leastNum.end(); iter++) cout << *iter << " "; cout <<endl; }
相关文章推荐
- 算法题12 查找最小的k个元素
- 【算法总结-top K】堆--查找最小(大)的k个元素
- 微软算法100题05 查找最小的k 个元素
- 程序员面试题精选100题(05)-查找最小的k个元素[算法]
- 面试算法:lg(k)时间查找两个排序数组合并后第k小的元素
- 设计一个最优算法来查找n个元素数组中的最大值和最小值
- 算法之查找第k大的元素
- 笔试算法题(05):转换BST为双向链表 & 查找栈中的最小元素
- 字符串算法——查找有序数组旋转后的最小值(无重复元素)(Find Minimum in Rotated Sorted Array)
- 查找最小的k 个元素之C#算法实现
- 算法习题6:查找最小的k个元素
- 查找最小的k个元素的自写算法
- 算法代码实现之选出第k小元素、中位数、最小的k个元素(线性复杂度),Golang(Go语言)实现
- 每天一算法(查找最小的k个元素(数组))
- 算法与数据结构面试题(5)-查找最小的k 个元素
- 设计一个最优算法来查找一n个元素数组中的最大值和最小值。已知一种需要比较2n次的方法,请给一个更优的算法。
- 字符串算法——查找有序数组旋转后最小值(有重复元素)(Find Minimum in Rotated Sorted Array II)
- 算法实验一:二分查找算法改进: 当搜索元素x不存在时,返回小于x的最大元素位置i和大于x的最小元素位置j. 当搜索元素在数组中时,i和j相同,均为x在数组中的位置。
- 【算法总结-top K】堆--查找最小(大)的k个元素
- 查找最小的k个元素[算法]