zoukankan      html  css  js  c++  java
  • 剑指Offer

    剑指Offer - 九度1371 - 最小的K个数
    2013-11-23 15:45
    题目描述:

    输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

    输入:

    每个测试案例包括2行:

    第一行为2个整数n,k(1<=n,k<=200000),表示数组的长度。

    第二行包含n个整数,表示这n个数,数组中的数的范围是[0,1000 000 000]。

    输出:

    对应每个测试案例,输出最小的k个数,并按从小到大顺序打印。

    样例输入:
    8 4
    4 5 1 6 2 7 3 8
    
    样例输出:
    1 2 3 4
    题意分析:
      给定n个数,求出其中最小的k个数,n和k的范围都是20万。基本思路如下:
        1. 全排序n个数,然后顺着数出k个,时间复杂度O(n * log(n) + k),空间复杂度O(1)。
        2. 用最大堆来存k个数,剩下的n-k个数每个都和堆顶比较,比堆顶小时,就把堆顶元素替换掉。采取先pop()后push()的方法替换。时间复杂度O(n * log(k)),空间复杂度O(k)。
        3. 直接统计每个值出现的次数,要么用hash,要么用map。然后数出最小的k个值即可。时间复杂度O(n),空间复杂度O(S),S为数组元素的取值范围。
      根据此题的数据范围,n、k的大小不固定,可能很接近也可能差很远,所以方法1和方法2都可行。n和k接近时适合方法1,相差很远时适合方法2。方法3由于数组元素的取值范围太大,不可行。
      对于方法3,一个很适用的问题,就是统计高考分数和排名。总共750分满分,一个省几十万考生,用桶排序的思想很容易就能算出某分数的全省排名。
     1 // 652996    zhuli19901106    1371    Accepted    点击此处查看所有case的执行结果    1796KB    931B    950MS
     2 // 201311180313
     3 #include <cstdio>
     4 #include <queue>
     5 #include <vector>
     6 using namespace std;
     7 
     8 int main()
     9 {
    10     // min heap
    11     priority_queue<int, vector<int>, less<int> > pq;
    12     vector<int> vv;
    13     int n, k;
    14     int i, tmp;
    15     
    16     while(scanf("%d%d", &n, &k) == 2){
    17         while(!pq.empty()){
    18             pq.pop();
    19         }
    20         vv.clear();
    21         
    22         if(k > n){
    23             k = n;
    24         }
    25         for(i = 0; i < k; ++i){
    26             scanf("%d", &tmp);
    27             pq.push(tmp);
    28         }
    29         
    30         for(i = k; i < n; ++i){
    31             scanf("%d", &tmp);
    32             if(tmp < pq.top()){
    33                 pq.pop();
    34                 pq.push(tmp);
    35             }
    36         }
    37         
    38         while(!pq.empty()){
    39             vv.push_back(pq.top());
    40             pq.pop();
    41         }
    42         
    43         for(i = (int)vv.size() - 1; i >= 0; --i){
    44             if(i == (int)vv.size() - 1){
    45                 printf("%d", vv[i]);
    46             }else{
    47                 printf(" %d", vv[i]);
    48             }
    49         }
    50         printf("
    ");
    51         vv.clear();
    52     }
    53     
    54     return 0;
    55 }
  • 相关阅读:
    windows下大数据开发环境搭建(3)——Scala环境搭建
    windows下大数据开发环境搭建(1)——Java环境搭建
    windows下大数据开发环境搭建(2)——Hadoop环境搭建
    I/O复用
    SuRF : Practical Range Query Filtering with Fast Succinct Tries
    信号处理
    进程间通信
    简易内存分配器的实现
    socket编程(C++)
    C++—程序的内存分区
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3439072.html
Copyright © 2011-2022 走看看