zoukankan      html  css  js  c++  java
  • 输出前n大的数(分治)

    描述:给定一个数组包含n个元素,统计前m大的数并且把这m个数从大到小输 出。

    输入:

    第一行包含一个整数n,表示数组的大小。n < 100000。第二行包含n个整数,表示数组的元素,整数之间以一个空格分开 。每个整数的绝对值不超过100000000。 第三行包含一个整数m。m < n。

    输出:

    从大到小输出前m大的数,每个数一行。

    分析:排序后再输出,复杂度 O(nlogn)

       用分治处理:复杂度 O(n+mlogm) 

    思路:利用快速排序的思想,把前m大的都弄到数组最右边,然后对这最右边m个元素排序, 再输出

    关键 :O(n)时间内实现把前m大的都弄到数组最右边

    引入操作 arrangeRight(k): 把数组(或数组的一部分)前k大的 都弄到最右边,如何将前k大的都弄到最右边

    1)设key=a[0], 将key挪到适当位置,使得比key小的元素都在 key左边,比key大的元素都在key右边(线性时间完成)

    2) 选择数组的前部或后部再进行 arrangeRight操作

    代码:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define N 10000+5
    int a[N];
    int b[N];
    int n, m;
    bool compare(int x, int y) {
        return x > y;
    }
    void arrangeRight(int L, int R) {
        int j = L+1;
        for(int i = L+1; i <= R; i++) {
            if(a[i] < a[L]) {
                swap(a[i], a[j]);
                j++;
            }
        }
        j--;
        swap(a[j], a[L]);
        if(n - j == m) return;
        else if(n - j < m) arrangeRight(L, j-1);
        else if(n - j > m) arrangeRight(j+1, R);
    }
    int main() {
         scanf("%d", &n);
         for(int i = 0; i < n; i++) scanf("%d", &a[i]);
         scanf("%d", &m);
         arrangeRight(0, n-1);
         int count = 0;
        for(int i = n - m; i < n; i++) b[count++] = a[i];
        sort(b, b+m, compare); 
         for(int i = 0; i < m; i++) printf("%d ", b[i]);
        return 0;
    } 
    作者:kindleheart
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Java之Chat历程
    Java之静态方法中的内部类
    Java异常捕获之finally
    C语言复杂声明的本质与局限
    使用beyond compare或kompare作为git的对比、合并工具
    [二分] [洛谷] P1258 小车问题
    [STL] [洛谷] P1165 日志分析
    [洛谷] P2802 回家
    卡特兰数的应用
    [洛谷] P1722 矩阵Ⅱ
  • 原文地址:https://www.cnblogs.com/kindleheart/p/9413621.html
Copyright © 2011-2022 走看看