##剑指offer 5.2 时间效率2 -最小的K个数
来源:互联网 发布:网络空间安全搜索引擎 编辑:程序博客网 时间:2024/06/05 09:05
面试题30: 最小的K个数
解法一:最直观的解法莫过于将n个数按升序排列后输出前k个。但是就效率来看,这种方法并不是最理想的。
一种改进方法是借助快速排序中对数组的划分,以第k个元素对数组进行划分,使得比第k个数字小的数字都在其左边,比其大的数字都在它的右边。O(N)
算法的时间复杂度是O(n),是一种比较高效的解法。但是上述算法存在的问题是修改了原始数组数据,因此在不允许修改原始数据的情况下的应用就会受到限制。
void Swap(int &a, int &b) { int c = a; a = b; b = c; } int Partition(int data[], int length, int start, int end) { if(data == NULL || length <= 0) return -1; int index = start - 1; for(int i = start; i < end; ++i) { if(data[i] < data[end]) { ++index; swap(data[i], data[index]); } } ++index; Swap(data[index], data[end]); return index; } void GetKLeastNumbers(int data[], int length, int result[], int k) { if(data == NULL || length <= 0 || result == NULL || k <= 0) return; int start = 0, end = length - 1; int index = Partition(data, length, start, end); while(index != k - 1) // 第k个数作为数组划分依据 { if(index > k - 1) index = Partition(data, length, start, index - 1); else index = Partition(data, length, index + 1, end); } for(int i = 0; i < k; ++i) result[i] = data[i]; }
解法二:在不修改原始数据的前提条件下,我们可以创建一个大小为k的容器存放最小的k个数。再对n个整数进行遍历,如果容器中的数少于k个,则直接把读入的数存入容器;如果容器中的数大于等于k个,同时当前读入的数小于容器中最大的数,那么删除容器中最大的数,将该数读入容器,否则不做操作。
为了确保快速删除容器中最大的数,容器数据的存储可以考虑使用最大堆。由于最大堆的根结点的值大于它的子树中任意结点的值,因此可以在O(1)得到已有k个数中的最大者,删除和插入操作的时间则为O(lgk)。对n个数重复最大堆的插入、删除操作总的算法时间复杂度为O(nlgk)。
下面是使用STL multiset完成上述算法的实现代码。
上述两种方法都实现求最小k个数,虽然第二种方法比第一种方法慢一些,但是它并不修改原始数据,另外比较适用于海量数据处理的情形。因此两种方法各有优劣,实际应用时视具体情况确定算法的选用。
typedef multiset<int, greater<int> > IntHeap;///////////////////////////////////////////////////////////////////////// find k least numbers in a vector///////////////////////////////////////////////////////////////////////void FindKLeastNumbers( const vector<int>& data, // a vector of data IntHeap& leastNumbers, // k least numbers, output unsigned int k ){ leastNumbers.clear(); if(k == 0 || data.size() < k) return; vector<int>::const_iterator iter = data.begin(); for(; iter != data.end(); ++ iter) { // if less than k numbers was inserted into leastNumbers if((leastNumbers.size()) < k) leastNumbers.insert(*iter); // leastNumbers contains k numbers and it's full now else { // first number in leastNumbers is the greatest one IntHeap::iterator iterFirst = leastNumbers.begin(); // if is less than the previous greatest number if(*iter < *(leastNumbers.begin())) { // replace the previous greatest number leastNumbers.erase(iterFirst); leastNumbers.insert(*iter); } } }}
0 0
- ##剑指offer 5.2 时间效率2 -最小的K个数
- 剑指offer 30题 【时间效率】最小的K个数
- 剑指offer:(30)时间效率 :最小的K个数
- 【剑指offer】5.2时间效率——面试题30:最小的k个数
- 《剑指offer》刷题笔记(时间效率):最小的K个数
- 剑指offer:最小的k个数
- 【剑指offer】最小的k个数
- 剑指offer-30:最小的k个数
- 最小的k个数(剑指offer)
- 剑指offer--最小的K个数
- 剑指Offer之 - 最小的k个数
- 剑指offer-30 最小的K个数
- 剑指offer之最小的k个数
- 剑指offer 30 - 最小的k个数
- 《剑指offer》最小的K个数
- 【剑指Offer】最小的K个数
- 剑指offer—最小的K个数
- 剑指Offer-30-最小的k个数
- LeetCode | Permutations II
- Android开发闪光灯-你的手机能闪亮嘛?
- 16进制颜色(html颜色值)字符串转为UIColor
- HDU4414 Finding crosses(模拟 || DFS)
- ssh框架+sitemesh编辑器上传图片被加载装饰器问题导致上传图片失败
- ##剑指offer 5.2 时间效率2 -最小的K个数
- java基础之反射(1.认识class类)
- hdu 1151 最小路径覆盖
- hdu 3832 Earth Hour (最短路变形)
- Swift(1):常量与变量
- 必须得对自己狠一些
- Oracle正则表达式用法
- Spring中的@Transactional配置
- org.hibernate.NonUniqueObjectException