描述
给定一个数组,统计前k大的数并且把这k个数从大到小输出。
输入
第一行包含一个整数n,表示数组的大小。n < 100000。
第二行包含n个整数,表示数组的元素,整数之间以一个空格分开。每个整数的绝对值不超过100000000。
第三行包含一个整数k。k < n。
输出
从大到小输出前k大的数,每个数一行。
样例输入
10
4 5 6 9 8 7 1 2 3 0
5
样例输出
9
8
7
6
5
思路
直接排序的话,时间复杂度是O(nlogn),可以优化一下,只给前k大的数排序。那么就先要挑出前k大的数,这里用到了快速排序中的部分算法。先从数组中挑出一个元素作为主元,然后将大于它的都放在它的左边,小于它的都放在它的右边。返回它的下标m,这样就找出了前m大的数,如果m=k,就完成了,再排序就行。如果m>k,那就继续在(0,m)之间继续,如果m<k,那么排出的数不够,需要在m之后的数继续找。
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
long int a[100001];
int partition(long int a[],int l,int r)
{
long int pivot=a[l];
int left=l+1,right=r;
while(left<=right)
{
if(a[left]>=pivot)
left++;
else
{
swap(a[left],a[right]);
right--;
}
}
swap(a[l],a[right]);
return right;
}
int main()
{
int n,k;
cin>>n;
for(int i=0;i<n;i++)
scanf("%ld",&a[i]);
cin>>k;
int m,left=0,right=n-1;
while(1)
{
m=partition(a,left,right);
if(m==k)
break;
else if(m>k)
right=m-1;
else
left=m+1;
}
sort(a,a+k);
for(int i=k-1;i>=0;i--)
printf("%d\n",a[i]);
return 0;
}