题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
一个简单的方法就是排序,先将这n个数按从大到小排序,最快需要O(nlogn)的时间,然后可以在O(1)时间内将K个数取出,显然这不是我们想要的结果。
我们可以给出一个容器,这个容器刚好能存放k个数,依次扫描N个整数,如果容器里数的个数小于K,那么直接将当前扫描到的整数存放到容器中,否则,将当前整数与容器中的最大数比较,如果比容器中的最大数还要大,那么将其抛弃,否则将容器中的最大数删除,将当前整数插入。
因此,我们只要对N个整数做三件事
1.在K个整数中找到最大数
2.在容器中删除最大数
3.插入一个新的数字
容器的数据结构可以用大根堆来实现,所以三步加起来在O(1)时间内可以完成(1:O(1);2,3:O(logK))
N个数总共要O(NlogK)时间复杂度明显提高
在C++中,我们还可以用基于红黑树的 multiset数据结构来实现,下面是何海涛博客中的代码,贴出来,大家参考下
typedef multiset<int, greater<int> > IntHeap;
void FindKLeastNumbers
(
const vector<int>& data, // 所有的整数数据
IntHeap& leastNumbers, // 输出K个最小的整数
unsigned int k
//表示容器的大小
)
{
leastNumbers.clear(); //清空该容器
if(k == 0 || data.size() < k) //排除特殊情况,鲁棒性
return;
vector<int>::const_iterator iter = data.begin();
for(; iter != data.end(); ++ iter)
{
//如果当前容器里的整数个数还没有达到K个,那么直接将当前整数插入到容器中
if((leastNumbers.size()) < k)
leastNumbers.insert(*iter);
//否则
else
{
//第一步 找出容器中的最大的整数
IntHeap::iterator iterFirst = leastNumbers.begin();
//第二步 比较当前整数与容器中最大整数的大小,如果小于
if(*iter < *(leastNumbers.begin()))
{
//替换掉容器中的最大整数
leastNumbers.erase(iterFirst);
leastNumbers.insert(*iter);
}
}
}
}
本篇文章对应何海涛博客
http://zhedahht.blog.163.com/blog/static/2541117420072432136859
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
一个简单的方法就是排序,先将这n个数按从大到小排序,最快需要O(nlogn)的时间,然后可以在O(1)时间内将K个数取出,显然这不是我们想要的结果。
我们可以给出一个容器,这个容器刚好能存放k个数,依次扫描N个整数,如果容器里数的个数小于K,那么直接将当前扫描到的整数存放到容器中,否则,将当前整数与容器中的最大数比较,如果比容器中的最大数还要大,那么将其抛弃,否则将容器中的最大数删除,将当前整数插入。
因此,我们只要对N个整数做三件事
1.在K个整数中找到最大数
2.在容器中删除最大数
3.插入一个新的数字
容器的数据结构可以用大根堆来实现,所以三步加起来在O(1)时间内可以完成(1:O(1);2,3:O(logK))
N个数总共要O(NlogK)时间复杂度明显提高
在C++中,我们还可以用基于红黑树的 multiset数据结构来实现,下面是何海涛博客中的代码,贴出来,大家参考下
typedef multiset<int, greater<int> >
void FindKLeastNumbers
(
)
{
}
本篇文章对应何海涛博客
http://zhedahht.blog.163.com/blog/static/2541117420072432136859