题目:输入n个整数,找出其中最小的K个数。例如输入4,5,1。6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
这道题类似于之前讲堆的那篇文章中,求公司员工喜欢的前K种水果,那道题我们可以使用最小堆解决,同样的思路,这道题我们可以使用最大堆解决,在最大堆中,根节点的值总是大于它的子树中任意节点的值。所以我们可以在O(1)时间内得到已有的K个数中的最大值,但需要O(logk)时间完成删除及插入操作。
这篇文章我们介绍另一种方法。
我们知道,STL中的容器set可以其中插入的元素进行排序,而multiset是一种允许数据冗余的set,且它们的底层都是红黑树,查找、删除和插入操作都只需O(logK)。
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<set>
#include <functional> // std::greater
using namespace std;
typedef multiset<int, greater<int>> inset;
typedef multiset<int, greater<int>>::iterator setiterator;
void GetLeastKNumbers(const vector<int>& data, inset& leastNumbers, int k)
{
leastNumbers.clear();
if (k < 1 || data.size() < k)
return;
vector<int>::const_iterator it = data.begin();
while (it != data.end())
{
if (leastNumbers.size() < k)
{
leastNumbers.insert(*it);
}
else
{
setiterator iterGreater = leastNumbers.begin();
if (*it < *iterGreater)
{
leastNumbers.erase(iterGreater);
leastNumbers.insert(*it);0
}
}
}
}