1. 程式人生 > >C++ 輸出前K大的數

C++ 輸出前K大的數

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;
}