• 【分治】输出前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 }
     
  • 相关阅读:
    缺陷与出路——一个游戏开发者的反思(转自《大众软件》)
    Arcengine 根据坐标串生成几何图形
    C#Arcengine通过坐标点生成面(环形)
    解析XML文件
    arcgis下载地址
    C#读写txt文件的两种方法介绍
    可伸缩性最佳实践:来自eBay的经验[精华强贴, 转之]
    请问怎样才能监视数据库表的变化?[转]
    VS2010中,在新建项目的时候,删除默认新建路径或曾经使用过的路径
    VS2010注册表垃圾清理
  • 原文地址:https://www.cnblogs.com/knmxx/p/9941521.html
Copyright © 2020-2023  润新知