1. 程式人生 > >【分治】輸出前k大的數

【分治】輸出前k大的數

描述

給定一個數組,統計前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)
用分治處理: 複雜度 O(n+mlogm)
思路:把前m大的都弄到陣列最右邊,然後對這最右邊m個元素排序,
再輸出
關鍵 : 利用快排思想在O(n)時間內實現把前m大的都弄到陣列最右邊
  1 #include<iostream>
  2 using namespace std;
  3 int n;
  4 int a[100010];
  5 int k;
  6 int partition(int s, int e)
  7 {
  8     int key = a[s];
  9     int i = s;
 10     int j = e;
 11     while (i < j)
 12     {
 13         while (a[j] >= key & i < j)
 14         {
 15             j--;
16 } 17 while (a[i] <= key & i < j) 18 { 19 i++; 20 } 21 swap(a[i], a[j]); 22 } 23 if (a[i] < key) 24 { 25 swap(a[s], a[i]); 26 } 27 else 28 swap(a[s], a[i - 1]); 29 return i; 30 } 31
void quickSort(int s,int e) 32 { 33 if (s < e) 34 { 35 int m = partition(s, e); 36 quickSort(s, m - 1); 37 quickSort(m+1, e); 38 } 39 } 40 void arrangeRight(int s,int e,int k) 41 { 42 if (e - s + 1 == k)//如果要找到大數個數就是陣列長度,不進行操作,直接排序 43 { 44 return; 45 } 46 //找一個基準數,使比這個數大的都在右邊,小的都在左邊 47 int key = a[s]; 48 int i = s; 49 int j = e; 50 while (i < j) 51 { 52 while ((a[j] >= key) && (i < j)) 53 { 54 j--; 55 } 56 while ((a[i] <= key) &&( i < j)) 57 { 58 i++; 59 } 60 swap(a[i], a[j]); 61 } 62 if (a[i] < key) 63 { 64 swap(a[s], a[i]); 65 } 66 else 67 { 68 swap(a[s],a[i-1]); 69 } 70 int index = i;//最後基準數的位置 71 int len = e - index + 1; 72 if (len == k) 73 { 74 return; 75 } 76 else if (len > k)//找到的大數多餘規定的,再往右縮小範圍 77 { 78 arrangeRight(index+1,e,k); 79 } 80 else//找到的大數不夠k個,往左擴大尋找範圍,已找到len個,還差len-m個 81 { 82 arrangeRight(s,index-1,k-len); 83 } 84 } 85 int main() 86 { 87 cin >> n; 88 for (int i = 0; i < n; ++i) 89 { 90 cin >> a[i]; 91 } 92 cin >> k; 93 arrangeRight(0, n - 1,k); 94 quickSort(n-k,n-1); 95 for (int i = n-1; i >= n - k; --i) 96 { 97 cout << a[i] << endl; 98 } 99 system("pause"); 100 return 0; 101 }