【剑指offer】数据流中的中位数

题目

        如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。

如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

 

思路

        采用大根堆+小根堆结合的方法,且满足:

        两个堆中的数据数目差不能超过1,这样可以使中位数只会出现在两个堆的交接处;

        大顶堆的所有数据都小于小顶堆,这样就满足了排序要求。

 

        1、插入的思路:

              1)若已读取的个数为偶数(包括0)时,两个堆的数目已经相同,将新读取的数插入到小顶堆中,从而实现小顶堆的个数多一。但是,如果新读取的数字比大顶堆中最大的数字还小,就不能直接插入到小顶堆中了 ,此时必须将新数字插入到大顶堆中,而将大顶堆中的最大数字插入到小顶堆中,从而实现小顶堆的个数多一。

         2)若已读取的个数为奇数时,小顶堆的个数多一,所以要将新读取数字插入到大顶堆中,此时方法与上面类似。

        2、取中位数的思路:

             当总个数为偶数时,使两个堆的数目相同,则中位数=大顶堆的最大数字与小顶堆的最小数字的平均值;

             而总个数为奇数时,使小顶堆的个数比大顶堆多一,则中位数=小顶堆的最小数字。

 

测试算例

        1.功能测试(读入奇/偶数个数字)

        2.边界值测试(读入0个、1个、2个数字)

 

总结

        1、使用Java提供的新的数据接口PriorityQueue,其默认内部是自然排序,结果为小顶堆,也可以自定义排序器,比如下面反转比较,完成大顶堆。

PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
        public int compare(Integer i1,Integer i2){
            return i2-i1;
        }
    });

        2、优先队列常见方法:

              1)offer:往队列中加元素,在插入失败时抛出异常。

                    add:往队列中加入元素,插入失败会返回false。

              2)element:获取但不删除队首元素,操作失败会抛出异常。

                    peek:获取但不删除队首元素,操作失败会返回null。

              3)remove:获取并删除队首元素,区别是当方法失败时会抛出异常;

                    poll:该方法返回队列头部的元素,如果队列为空,则返回NULL。

              4)队列求大小为.size()

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值