1:输出前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
首先借助了快速排序的思想,一次快速排序之后,存在一个key牌,左边的数都小于这个key,右边的数都大于key,所以只要右边的数的个数刚好等于k那么就能找到这个数,在对右边的数进行排序就行
定义arrangeRight为操作使得右边的数为k,如果右边的数大于k,那么对右边部分递归调用这个函数
如果右边的数小于k,那么对左边e-j-s个数进行操作,使得右边的数等于k
最后在对k个数进行排序,时间复杂度是O(n+klogk)
#include<iostream>
#include<algorithm>
#define N 100010
using namespace std;
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void quicksort(int a[], int s, int e, int k)
{
// s 是数组的开始,e是数组的最后一个元素,k要求的前k个最大值
int m = a[s];
if (s >= e)
return;
int i = s, j = e;
while (i != j)
{
while (j > i&&a[j] >= m)
{
j--;
}
swap(a[i], a[j]);
while (j > i&&a[i] <= m)
{
i++;
}
swap(a[i], a[j]);
}
//quicksort(a, s, i - 1);
//quicksort(a, i + 1, e);
if ((e - j) == k)
{
// 如果已经有k个数在key的右边,则目标完成
return;
}
else if ((e - j) > k)
{
// 对右边的从j到e的数进行操作
quicksort(a, j, e, k);
}
else
{
// 对从s到j的数
quicksort(a, s, j, e - j - k);
}
}
int main()
{
int n, k;
int a[N];
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
scanf("%d", &k);
quicksort(a, 0, n - 1, k);
sort(a+n-k, a + n);
for (int i = n-1; i >= n-k; i--)
{
printf("%d\n", a[i]);
}
return 0;
}