问题描述:
输入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 }
转载自源代码