OpenJudge 010:输出前k大的数

010:输出前k大的数

总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB
描述
给定一个数组,统计前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

思想
本题由于只需要最大的k个数有序,而其余n-k个数是不需要有序的,因此可以找到最大的k个数(无论有序有否)再对其进行排序即可。总体的思想就是对部分排序时间更少。

而查找的话,就可以利用一个快速排序中的分治思想,用基准数来将比其大的和比其小的数分在其两旁,当且仅当该基准数(包含该基准数)到数组末尾的元素个数为k时满足要求;而元素个数比k小时(假设此时基准数以及其右边的元素个数为m),就说明还需要在基准数左边进行查找较大的k-m个元素;而当元素个数大于k时,就只需要在基准数右边缩小区间查找即可。

代码

#include<iostream>
#include<algorithm>
using namespace std;

void FindMaxK(int* ar, int l, int r, const int k) {
	int i = l, j = r;
	int tmp = ar[l];
	while (i < j) {
		while (i < j && ar[j] >= tmp)
			--j;
		swap(ar[i], ar[j]);
		while (i < j && ar[i] <= tmp)
			++i;
		swap(ar[i], ar[j]);
	}

	if (r - i + 1 < k)
		FindMaxK(ar, l, i - 1, k - (r - i + 1));//在基准数左边查找剩余个数的元素
	else if (r - i + 1 == k)//满足条件
		return;
	else
		FindMaxK(ar, i + 1, r, k);//在基准数右边缩小查找区间
}

void show(int* ar, int k, int n) {
	FindMaxK(ar, 0, n - 1, k);

	sort(ar + n - k, ar + n);//对末尾最大的k个元素排序并输出即可
	for (int i = 0; i < k; ++i)
		cout << ar[n - i - 1] << endl;
}

int main() {
	int n = 0;
	cin >> n;
	int* ar = new int[n];

	for (int i = 0; i < n; ++i)
		cin >> ar[i];

	int k = 0;
	cin >> k;

	show(ar, k, n);

	delete[]ar;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值