分治输出前k大的数

Posted knmxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分治输出前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 }
 









以上是关于分治输出前k大的数的主要内容,如果未能解决你的问题,请参考以下文章

010:输出前k大的数

openjudge 7617:输出前k大的数

输出前 k 大的数

OpenJ_Bailian 7617 输出前k大的数

统计前k大的数x

求第K大数(分治)