输出前m的的数
例题一:输出前m大的数:
描述
给定一个数组包含n个元素,统计前m大的数并且把这m个数从大到小输出。
输入
第一行包含一个整数n,表示数组的大小。n < 100000。 第二行包含n个整数,表示数组的元素,整数之间以一个空格分开。每个整数的绝对值不超过100000000。 第三行包含一个整数m。m < n。
输出
从大到小输出前m大的数,每个数一行。
方法1:对全体的数字进行归并排序,输出前m大的数(O(nlogn))代码:
#includeusing namespace std; int a[1000000],temp[1000000]; void Merge(int *a,int s,int e,int m,int *tmp){ int pb = 0; int p1 = s,p2 = e; while(p1<=m&&p2<=e){ if(a[p1]<a[p2]){ tmp[pb++] = a[p1++]; }else{ tmp[pb++] = a[p2++]; } } while(p1<=m){ tmp[pb++] = a[p1++]; } while(p2<=e){ tmp[pb++] = a[p2++]; } for(int i = 0;i 1;i++){ a[s+i] = tmp[i]; } } void MergeSort(int *a,int s,int e,int *tmp){ if(s < e) { int m = s+(e-s)/2; MergeSort(a,s,m,tmp); MergeSort(a,m+1,e,tmp); Merge(a,s,m,e,tmp); } } int main(){ int n,m; while(cin>>n>>m){ for(int i = 0;i ){ cin>>a[i]; } MergeSort(a,0,n-1,temp); for(int i = n-m;i ){ if(i == n-m){ cout<<a[i]; }else{ cout<<","<<a[i]; } } cout<<endl; } return 0; }
方法二:
用分治处理:复杂度 O(n+mlogm)
思路:把前m大的都弄到数组最右边,然后对这最右边m个元素排序,再输出
关键 :O(n)时间内实现把前m大的都弄到数组最右边
引入操作 arrangeRight(k): 把数组(或数组的一部分)前k大的都弄到最右边
如何将前k大的都弄到最右边
1)设key=a[0], 将key挪到适当位置,使得比key小的元素都在key左边,比key大的元素都在key右边(线性时间完成)——也就是使用一次快速排序的过程
2) 选择数组的前部或后部再进行 arrangeRight操作
a = k done 表示完成此过程
a > k 对此a个元素再进行arrangeRigth(k)
a < k 对左边b个元素再进行arrangeRight(k-a)
(这个地方引入图像加深思考)
有a个数是比key大的,b个是比key更小的,现在开始比较前k个数在这个数组里面的分布,有三种情况,第一种情况就是k==a这个就是说明刚好前a个大刚好满足题目的要求,如果a>k说明只要对右边再次找arrangeRight(k),如果是a 这个地方要注意一下,arrangeRight这个函数做的只是把所有前m大的数放在右边。一旦总数量到达了m就会return。只要数据规模足够大的话后面的速度就会比前面快很多。 代码参考:(92条消息) 输出前m大的数_Jamence的博客-CSDN博客#include