zoukankan      html  css  js  c++  java
  • 《Cracking the Coding Interview》——第18章:难题——题目6

    2014-04-29 02:27

    题目:找出10亿个数中最小的100万个数,假设内存可以装得下。

    解法1:内存可以装得下?可以用快速选择算法得到无序的结果。时间复杂度总体是O(n)级别,但是常系数不小。

    代码:

      1 // 18.6 Find the smallest one million number among one billion numbers.
      2 // Suppose one billion numbers can fit in memory.
      3 // I'll use quick selection algorithm to find them. This will return an unsorted result.
      4 // Time complexity is O(n), but the constant factor may be massive. I don't quite like this algorithm.
      5 #include <algorithm>
      6 #include <iostream>
      7 #include <vector>
      8 using namespace std;
      9 
     10 const int CUT_OFF = 3;
     11 
     12 int medianThree(vector<int> &v, int ll, int rr)
     13 {
     14     int mm = (ll + rr) / 2;
     15 
     16     if (v[ll] > v[mm]) {
     17         swap(v[ll], v[mm]);
     18     }
     19     if (v[ll] > v[rr]) {
     20         swap(v[ll], v[rr]);
     21     }
     22     if (v[mm] > v[rr]) {
     23         swap(v[mm], v[rr]);
     24     }
     25     swap(v[mm], v[rr - 1]);
     26     return v[rr - 1];
     27 }
     28 
     29 void quickSelect(vector<int> &v, int ll, int rr, int k)
     30 {
     31     // reference from "Data Structure and Algorithm Analysis in C" by Mark Allen Weiss.
     32     int pivot;
     33     int i, j;
     34     
     35     if (ll + CUT_OFF <=    rr) {
     36         pivot = medianThree(v, ll, rr);
     37         i = ll;
     38         j = rr - 1;
     39         
     40         while (true) {
     41             while (v[++i] < pivot);
     42             while (v[--j] > pivot);
     43             if (i > j) {
     44                 break;
     45             }
     46             swap(v[i], v[j]);
     47         }
     48         swap(v[i], v[rr - 1]);
     49     
     50         if (k < i) {
     51             return quickSelect(v, ll, i - 1, k);
     52         } else if (k > i) {
     53             return quickSelect(v, i + 1, rr, k);
     54         }
     55     } else {
     56         for (i = ll; i <= rr; ++i) {
     57             for (j = i + 1; j <= rr; ++j) {
     58                 if (v[i] > v[j]) {
     59                     swap(v[i], v[j]);
     60                 }
     61             }
     62         }
     63     }
     64 }
     65 
     66 int main()
     67 {
     68     vector<int> v;
     69     vector<int> res;
     70     int n, k;
     71     int i;
     72     int k_small, count;
     73     
     74     while (cin >> n >> k && (n > 0 && k > 0)) {
     75         v.resize(n);
     76         for (i = 0; i < n; ++i) {
     77             cin >> v[i];
     78         }
     79 
     80         // find the kth smallest number
     81         // this will change the order of elements
     82         quickSelect(v, 0, n - 1, k - 1);
     83         k_small = v[k - 1];
     84         count = k;
     85         for (i = 0; i < n; ++i) {
     86             if (v[i] < k_small) {
     87                 --count;
     88             }
     89         }
     90         for (i = 0; i < n; ++i) {
     91             if (v[i] < k_small) {
     92                 res.push_back(v[i]);
     93             } else if (v[i] == k_small && count > 0) {
     94                 res.push_back(v[i]);
     95                 --count;
     96             }
     97         }
     98         
     99         cout << '{';
    100         for (i = 0; i < k; ++i) {
    101             i ? (cout << ' '), 1 : 1;
    102             cout << res[i];
    103         }
    104         cout << '}' << endl;
    105         
    106         v.clear();
    107         res.clear();
    108     }
    109     
    110     return 0;
    111 }

    解法2:如果要求结果也是有序的,那可以用最大堆得到有序结果。时间复杂度是O(n * log(m))级别,思路和代码相比快速选择算法都更简单,不过效率低了些。

    代码:

     1 // 18.6 Find the smallest one million number among one billion numbers.
     2 // Suppose one billion numbers can fit in memory.
     3 // I'll use a max heap, which runs in O(n * log(k)) time, returns a sorted result.
     4 #include <iostream>
     5 #include <queue>
     6 #include <vector>
     7 using namespace std;
     8 
     9 template <class T>
    10 struct myless {
    11     bool operator () (const T &x, const T &y) {
    12         return x < y;
    13     };
    14 };
    15 
    16 int main()
    17 {
    18     int val;
    19     int n, k;
    20     int i;
    21     // max heap
    22     priority_queue<int, vector<int>, myless<int> > q;
    23     vector<int> v;
    24     
    25     while (cin >> n >> k && (n > 0 && k > 0)) {
    26         k = k < n ? k : n;
    27         for (i = 0; i < k; ++i) {
    28             cin >> val;
    29             q.push(val);
    30         }
    31         
    32         for (i = k; i < n; ++i) {
    33             cin >> val;
    34             if (q.top() > val) {
    35                 q.pop();
    36                 q.push(val);
    37             }
    38         }
    39         while (!q.empty()) {
    40             v.push_back(q.top());
    41             q.pop();
    42         }
    43         reverse(v.begin(), v.end());
    44         
    45         cout << '{';
    46         for (i = 0; i < k; ++i) {
    47             i ? (cout << ' '), 1 : 1;
    48             cout << v[i];
    49         }
    50         cout << '}' << endl;
    51         
    52         v.clear();
    53     }
    54     
    55     return 0;
    56 }
  • 相关阅读:
    sass环境搭建之node-sass,ruby
    对于模块加载:ES6、CommonJS、AMD、CMD的区别
    sass变量的作用域
    sass中的占位符%,@extend,@mixin(@include)的编译区别和使用场景
    遇到的问题
    全局配置
    组件或者dom的特殊属性
    全局API
    CentO7安装zookeeper并设置开机自启动
    MyBatis中TypeHandler的使用
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3698369.html
Copyright © 2011-2022 走看看