IT公司100题-5-查找最小的k个元素

问题描述:
输入n 个整数,输出其中最小的k 个。
例如输入8, 7, 6, 5, 4, 3, 2, 1这8 个数字,则最小的3 个数字为3, 2, 1。
 
分析:
时间复杂度O(nlogn)方法:
对n个整数升序排序,取数组前面k个数就是最小的k个数,时间复杂度为O(nlogn),空间复杂度为O(1)。
 
大顶堆,时间复杂度为O(nlogk):
我们可以采用大顶堆来保存最小的k个数,堆顶元素就是k个最小的数中最大的。新来一个元素的时候,与堆顶元素进行比较,如果比堆顶元素大,则直接丢弃。如果比堆顶元素小,则替换堆顶元素,并且进行大顶推的调整,需要O(logk)的时间。所以总的时间复杂度为O(nlogk),空间复杂度为O(k)。
 
STL multiset,时间复杂度为O(nlogk):
multiset容器的内部结构通常由平衡二叉树(balanced binary tree)来实现,所以查找、删除和插入操作都只需要O(logk)的时间。当元素放入容器中时,会按照一定的排序法则自动排序,默认是按照less<>排序规则来排序。将其按照greater<>排序后,multiset的第一个元素就是容器中的最大元素。

为了保证multiset有序,如果要修改multiset元素的值,必须先删除,后插入。

 1 // 5.cc
 2 #include <iostream>
 3 #include <vector>
 4 #include <set>
 5 using namespace std;
 6 
 7 // 查找最小的k个数
 8 typedef multiset<int, greater<int> > max_heap;
 9 void find_k_least(const vector<int>& data, max_heap& heap, size_t k) {
10     heap.clear();
11 
12     if(k == 0 || data.size() < k)
13         return;
14 
15     vector<int>::const_iterator it;
16     for(it = data.begin(); it != data.end(); ++ it) {
17         if((heap.size()) < k)
18             heap.insert(*it);
19         else {
20             max_heap::iterator it_first = heap.begin();  // 最大元素
21             if(*it < *it_first) {  // 比堆中的最大元素小
22                 heap.erase(it_first);
23                 heap.insert(*it);
24             }
25         }
26     }
27 }
28 
29 int main() {
30     vector<int> data;
31     for (int i = 10; i > 0; i--)
32         data.push_back(i);
33     size_t k = 4;
34     max_heap heap;
35     find_k_least(data, heap, k);
36 
37     max_heap::const_iterator it;
38     for (it = heap.begin(); it != heap.end(); ++it)
39         cout << *it << " ";
40     cout << endl;
41 
42     return 0;
43 }

转载自源代码

本文链接地址: http://w.worthsee.com/index.php/5-%e6%9f%a5%e6%89%be%e6%9c%80%e5%b0%8f%e7%9a%84k%e4%b8%aa%e5%85%83%e7%b4%a0/

posted on 2014-07-29 12:17  醉清风JM  阅读(320)  评论(0编辑  收藏  举报

导航