剑指Offer-30-最小的k个数-最大堆

先创建一个大小为K的数据容器来存储最小的K个数,接下来我们每次从输入的n个整数中读入一个数,如果容器中已有的数字少于K,则直接把这次读入的整数放入容器中;如果容器中已有K个数,就是容器满了,此时我们不能插入新的数字而只能替换已有的数字了。找出这K个数的最大值,然后拿这次待插入的整数和最大值相比较。如果待插入的值比当前已有的最大值小,则用这个数替换当前已有的最大值;如果待插入的值比当前已有的最大值还大,那么这个数不可能是最小的K个整数之一,于是我们可以抛弃这个数。
我们可以用二叉树(红黑树或最大堆)来实现这个数据容器。堆查找最大值O(1),删除插入为O(logk);红黑树查找、删除和插入都是O(logk)。
第2种情况非常适合海量数据的处理,当n>>k的时候非常适合。
时间复杂度为:O(n*lgk)

#include <iostream>
#include <set>
#include <vector>

using namespace std;
typedef multiset<int,greater<int> > intSet;
typedef multiset<int,greater<int> >::iterator  setIterator;

void MinK(const vector<int>& data,intSet& leastNumbers,int k) {
    leastNumbers.clear();

     if(k < 1 || data.size() < k)
            return;
     vector<int>::const_iterator iter = data.begin();
     for(; iter != data.end(); ++ iter) {
         if(leastNumbers.size()<k) {
             leastNumbers.insert(*iter);
         }
         else {
             setIterator iterGreatest = leastNumbers.begin();
             if(*iterGreatest > *iter) {
                 leastNumbers.erase(iterGreatest);
                 leastNumbers.insert(*iter);
             }
         }
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值