例题3:输出前k大的数
描述:给定一个数组包含n个元素,统计前k大的数并且把这k个数从大到小输出。
输入:第一行包含一个整数n,表示数组的大小。n<100000
第二行包含n个整数,表示数组的元素,整数之间以一个空格分开。每个整数的绝对值不超过100000000.
第三行包含一个整数k,k<n.
输出:
从大到小输出前k大的数,每个数一行。
解析:
引入操作arrangeRight(k):把数组(或数组的一部分前k大的都弄到最右边
如何将前k大的都弄到最右边?
第一步:设key=a[0],将key挪到适当位置,使的比key小的元素都在key左边,比key大的元素都在key右边。
第二步:选择数组的前部或后部再进行arrangeRight操作

/**
输出前m大的数
排序后在输出,复杂度O(nlogn)
用分治后处理,复杂度O(n+mlogm)
思路:把前m大的都弄到数组最右边,然后对着最右边的m个元素排序后在输出
*/
#include<iostream>
#include<algorithm>
#define maxsize 100010
using namespace std;
void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
}
void arrangeRight(int a[],int left,int right,int k)
{
if(left>=right)
return;
int i=left,j=right,temp=a[i];
while(i!=j)
{
while(i<j&&a[j]>=temp)
j--;
swap(a[i],a[j]);
while(i<j&&a[i]<temp)
i++;
swap(a[i],a[j]);
}
if(right-i+1==k)//右边部分直接等于k
return;
else if(right-i+1>k)//右边部分比k的个数多
arrangeRight(a,i+1,right,k);
else if(right-i+1<k)//右边部分比k的个数少
arrangeRight(a,left,i-1,k-(right-i+1));
}
int main()
{
int a[maxsize];
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
int k;
cin>>k;
arrangeRight(a,0,n-1,k);
//调用sort函数排序
sort(a+n-k,a+n); //注意sort函数第一个参数是要排序的数组的起始位置 第二个是要 结束的地址(最后一位要排序的地址的下一位置)
for(int i=n-1;i>=n-k;i--)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
683



被折叠的 条评论
为什么被折叠?



