何海涛算法面试题感悟之五:查找最…

题目:输入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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值