转自 http://anwj336.blog.163.com/blog/static/89415209201010110025364/
题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
分析:这道题最简单的思路莫过于把输入的n个整数排序,这样排在最前面的k个数就是最小的k个数。只是这种思路的时间复杂度为O(nlogn)。我们试着寻找更快的解决思路。
我们可以开辟一个长度为k的数组。每次从输入的n个整数中读入一个数。如果数组中已经插入的元素少于k个,则将读入的整数直接放到数组中。否则长度为k的数组已经满了,不能再往数组里插入元素,只能替换了。如果读入的这个整数比数组中已有k个整数的最大值要小,则用读入的这个整数替换这个最大值;如果读入的整数比数组中已有k个整数的最大值还要大,则读入的这个整数不可能是最小的k个整数之一,抛弃这个整数。这种思路相当于只要排序k个整数,因此时间复杂可以降到O(n+nlogk)(最坏情况下需要更新n-k次)。通常情况下k要远小于n,所以这种办法要优于前面的思路。
这是我能够想出来的最快的解决方案。不过从给面试官留下更好印象的角度出发,我们可以进一步把代码写得更漂亮一些。从上面的分析,当长度为k的数组已经满了之后,如果需要替换,每次替换的都是数组中的最大值。在常用的数据结构中,能够在O(1)时间里得到最大值的数据结构为最大堆。因此我们可以用堆(heap)来代替数组。
另外,自己重头开始写一个最大堆需要一定量的代码。我们现在不需要重新去发明车轮,因为前人早就发明出来了。同样,STL中的set和multiset为我们做了很好的堆的实现,我们可以拿过来用。既偷了懒,又给面试官留下熟悉STL的好印象,何乐而不为之?
#include <set>
#include <vector>
#include <iostream>
using namespace std;
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);
}
}
}
}
分享到:
相关推荐
输出一组元素中的最小的k个元素。例如数据集为:{1、8、3、6、5、4、7、2},则最小的4个数字为1,2,3和4。 【基本要求】 由随机数产生测试数据,测试数据不小于10000个,测试k的不同取值对算法的影响,如k=10、50、...
在计算机科学中,"算法中最小K元素的选择问题"是一个重要的数据结构和算法主题,它涉及到从一个无序或有序的数组中找到第K小(或大)的元素。这个问题在各种应用场景中都有广泛的应用,比如数据库查询优化、排序算法...
这个问题的基本目标是从一个未排序或已排序的数组或集合中找出第k个最小的元素。这里我们将深入探讨三种方法来解决这个问题:中位选择法、随机选择查找以及排序查找。 1. **中位选择法**: 中位选择法是一种高效...
3. 计算基准元素所在位置的索引,如果这个索引等于k-1,则基准就是第k个最小元素;如果索引小于k-1,说明第k个最小元素在基准右边的子数组中;如果索引大于k-1,则第k个最小元素在基准左边的子数组中。 4. 递归地在...
创建一个大小为k的最小堆,将数组的前k个元素放入堆中。之后,遍历数组剩余的元素,如果元素小于堆顶元素(即第k小元素),则替换堆顶元素并重新调整堆。最后,堆顶元素即为第k小元素。这种方法的时间复杂度为O(n ...
在给定的标题“查找第k小2”中,我们可以推断这是一个关于查找第k小元素的算法问题的第二个版本,可能与之前的实现有所不同或者更进阶。描述提到“完成算法课程作业,随机生成1000个数字,短时间内找到第k小”,这...
2. **优先队列/堆**:使用最小堆来存储前K个元素,每次插入新元素时,如果堆的大小超过K,则将堆顶元素(最大值)移除,这样可以保证堆中始终包含当前的K个最小元素。 3. **线性时间复杂度的解决方案**:例如,可以...
当弹出的元素个数等于k-1时,堆顶剩下的元素就是第k小的元素。堆排序法的时间复杂度为O(n log n)。 3. **线性时间复杂度的解决方案**: 当数据集支持随机访问时,可以使用“最小堆+跳跃”算法,也称为“三数取中”...
描述部分提供了一个具体的例子,说明了如何找出数组中的最小K个数。例如,对于数组`[4, 5, 1, 6, 2, 7, 3, 8]`,我们要找的是最小的4个数,即`[1, 2, 3, 4]`。在示例1中,输入数组为`[3, 2, 1]`,K值为2,输出可以是...
标题中的“查找第i小的元素”是指在一组无序数据中找到第i个最小的元素,例如在未排序的数组或集合中找到第k小的元素,这是一个常见的算法问题,广泛应用于各种数据结构和算法的实践中。这个问题的解决方法通常涉及...
在这个问题中,我们要在数组中找到第k个最小的元素,同时考虑到数组中可能存在重复的元素。这个问题在实际应用中广泛出现,比如数据库查询优化、数据分析以及在线竞赛编程等场景。 在Visual C++环境下实现寻找第k小...
在Python编程中,查找最小的k个数是一个常见的问题,特别是在数据处理和算法竞赛中。这个问题要求从一个整数列表中找到最小的k个元素。这里提供了两种不同的解决方案。 **解法1:基于快速选择的Partition函数** ...
该算法的目标是在一个无序的数列中找出前k个最小的元素,而不仅仅是找到最小值或次小值。以下是对这一知识点的深入解析。 ### 1. 算法原理 #### SELECT算法 给定文件中提到的“SELECT”算法是一种高效的查找数列...
TopK算法的主要目标是从大量数据中找出前K个最大的(或最小的)元素。这里的“给力实现”可能意味着这种方法在性能和效率上有显著优势。 **描述分析:** 描述简洁地重申了标题中的主题,表明我们将专注于如何使用...
选择排序在每一轮中找到当前未排序部分的最大(或最小)元素,将其放到正确的位置,因此需要进行K轮,总时间复杂度为O(kn)。堆排序可以建立一个大顶堆,然后每次取出堆顶元素,重复K次,时间复杂度为O(nlogk)。这些...
该方法首先将数组转换为最小堆,然后将最小值保存起来,然后将最后一个元素提升到第一个元素,重新构建最小堆,这样进行K次的最小堆创建,就找到了前K个最小值。这种方法的时间复杂度为O(n log k),并且不需要额外的...
为了分析和验证这些算法,你可以参考"排序查找最小的第k个数.docx"文档,它可能包含了具体的代码示例和进一步的解释。同时,"example"可能是实现这些算法的一个测试用例或者数据集,用于检查算法的正确性。 总之,...
这个任务通常涉及到排序和查找技术,而在这个特定的案例中,我们使用C++语言来实现,并且采取了一种将元素划分为9个一组的策略来优化时间复杂度。 首先,我们需要理解“第k小元素”的概念。在非降序排列的数组中,...
在C语言中,处理大数据集并找出其中最大的k个数或最小的k个数是一个常见的问题,这通常涉及到数据结构中的“堆”概念。堆是一种特殊的树形数据结构,满足以下性质:每个父节点的值要么大于等于其子节点(大顶堆),...
在给定的编程问题中,任务是找到两个已排序整数数组 `nums1` 和 `nums2` 中和最小的 `k` 对数字。这个问题属于算法的范畴,具体是组合优化问题,通常在数据结构和算法的学习中作为 LeetCode 等在线编程平台上的挑战...