【剑指Offer系列】41-数据流中的中位数(大小顶堆结合)

中位数简介
  • 找出这组数据:23、29、20、32、23、21、33、25 的中位数。
    首先将该组数据进行排列(这里按从小到大的顺序),得到:
    20、21、23、23、25、29、32、33
    因为该组数据一共由8个数据组成,即n为偶数,故按中位数的计算方法,得到中位数,即第四个数和第五个数的平均数。
    midval = (23+25)/2 = 24

  • 找出这组数据:10、30、 20、 20、 20的中位数。
    首先将该组数据进行排列10、 20、 20、 20、 30
    因为该组数据一共由5个数据组成,即n为奇数,故按中位数的计算方法,得到中位数为20,即第3个数。

具体实现:
1.创建大顶堆(这里使用优先队列等效成大顶堆)queue2,和小顶堆queue1。(大顶堆弹出元素,先弹出大的值;小顶堆弹出元素,首先弹出值小的元素)

在这里插入图片描述

class MedianFinder {
    private Queue<Integer> smallQ, bigQ;

    public MedianFinder() {
        smallQ = new PriorityQueue<>(); // 小顶堆,保存较大的一半
        bigQ = new PriorityQueue<>((x, y) -> (y - x)); // 大顶堆,保存较小的一半
    }

    public void addNum(int num) {
    	// 奇数个数
        if (((bigQ.size() + smallQ.size()) & 1) == 1) {
            smallQ.add(num);
        } else {
            bigQ.add(num);
        }
        // 大顶堆的头(左侧较小的数中最大值) > 小顶堆的头(右侧较大的数中最小的值)
        // 则需要调换顺序
        if (bigQ.size() > 0 && smallQ.size() > 0 && bigQ.peek() > smallQ.peek()) {
            Integer big = bigQ.poll();
            Integer small = smallQ.poll();
            smallQ.add(big);
            bigQ.add(small);
        }
    }

    public double findMedian() {
        return ((bigQ.size() + smallQ.size()) & 1) == 1 ? bigQ.peek() : (bigQ.peek() + smallQ.peek()) / 2.0;
    }
}

测试

    public static void main(String[] args) {
        MedianFinder finder = new MedianFinder();
        List<Integer> list = Lists.newArrayList(10,30,40,20,50);
        for (Integer item : list) {
            finder.addNum(item);
            double median = finder.findMedian();
            System.out.println(median);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值