剑指offer--随时找到数据流的中位数

有一个远远不断的吐出整数的数据流,假设你有足够的空间来保存吐出的数,请设计一个名叫MedianHolder的结构,MedianHolder可以随时去的之前吐出所有数的中位数。

要求:1.如果MedianHolder已经保存了吐出的N个数,那么任意时刻将一个新数加入到MedianHolder的过程,其时间复杂度为O(logN)。

2.取得已经吐出的N个数整体的中位数的过程,时间复杂度为O(1)。

思路:准备两个堆,一个大根堆,一个小根堆。力争做到如果排完序之后,前n/2个数放在大根堆里面,后n/2个数放在小根堆里面。这样大根堆的堆顶和小根堆的堆顶就一定能压中中位数。比如7,3,4,5这样一个数据流,就把3,4放在大根堆里面,4在堆顶;7,5放在小根堆里面,5在堆顶。则4和5正好是可以压中中位数的位置。

具体做法是:一开始两个堆都是空的,遇到的第一个数默认放在大根堆里面,新的数记为new_number,如果这个数小于等于大根堆的堆顶,就把new_number放到大根堆的堆顶去;如果new_number大于大根堆的堆顶,就放到小根堆里面去。如果不平也好解决。比如如果第一个数是5,就把5放到大根堆里面,接下来再遇到3,则3放到大根堆里面去,这个时候大根堆有2个数,小根堆有0个数,而我们每加一个数,都考察一下两个堆的size大小是否超过1 。当一个size是2一个size是0的时候就超过了,这个时候大根堆的堆顶弹出一个5进小根堆,就又平了。接下里再遇到一个数6,大于大根堆的堆顶3,则6直接进小根堆;接下来又来一个数4,4比3大,则4也进小根堆,这时候两个堆size差值又超过1了,则小根堆的堆顶弹出一个4进大根堆,此时大根堆堆顶是5,小根堆堆顶是4,又压中了中位数的位置。所以整个策略就是,只关心大根堆的堆顶,判断当前数与大根堆堆顶的关系来决定当前数进大根堆还是小根堆。如果两个堆的size大小超过了1,就让较大的堆的堆顶弹出进另外一个堆。这样一直可以保证前n/2个数放在大根堆里面,后n/2个数放在小根堆里面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值