【重温经典】数据流的中位数

这篇博客探讨了两种方法来实时计算数据流的中位数,分别是使用大小根堆。第一种方法通过维护两个堆,一个大根堆和一个小根堆,确保堆的平衡来获取中位数。第二种方法同样利用大小根堆,但不使用计数器,而是依赖堆的大小关系。在后续的优化问题中,提出了在数据限定在0到100范围内时,可以使用计数数组来加速计算,以及当99%数据在一定范围内时,只关注该范围内的数据以提高效率。
摘要由CSDN通过智能技术生成

【重温经典】数据流的中位数

方法1:大小根堆

在这里插入图片描述

  • 维护maxHeap 和minHeap,保持maxHeap.size() = minHeap.size() 或者maxHeap.size() = minHeap.size()+1
  • maxHeap维护的数据属于整个数据流的下半部分的数据,minHeap维护的数据属于整个数据流上半部分的数据
  • 返回中位数的时候,注意总体的数据个数的奇偶性
class MedianFinder {

    //大根堆,从栈顶到栈底 依次从大到小
    PriorityQueue<Integer> maxHeap = new PriorityQueue<>(((o1, o2) -> o2 - o1));
    //小根堆,从栈顶到栈底 依次从小到大
    PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    int cnt = 0;


    /**
     * initialize your data structure here.
     */
    public MedianFinder() {

    }

    public void addNum(int num) {
        cnt++;
        maxHeap.offer(num);
        minHeap.offer(maxHeap.poll());
        if (cnt % 2 == 1) maxHeap.offer(minHeap.poll());
    }

    public double findMedian() {
        if(cnt %2 ==1 ){
            return maxHeap.peek();
        }else {
            return (maxHeap.peek()+minHeap.peek())/2.0;
        }
    }
}

方法2:大小根堆(不使用计数器)

  • 不使用计数器,用queue的size进行判断
class MedianFinder {
    PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>((o1, o2) -> o2 - o1);
    PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();

    public MedianFinder() {

    }

    public void addNum(int num) {
        maxHeap.offer(num);
        minHeap.offer(maxHeap.poll());
        if (maxHeap.size() < minHeap.size()) maxHeap.offer(minHeap.poll());
    }

    public double findMedian() {
        if (maxHeap.size() == minHeap.size())
            return (maxHeap.peek() + minHeap.peek()) / 2.0;
        else
            return maxHeap.peek();
    }
}

FollowUp

Q:如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法?

A:存储一个100范围的arr数组,记录0-100数据出现的个数,以及总的数据的个数,遍历arr数组,可以计算出中位数

Q:如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?

A:如上还是维持以上的一个arr数组,对于<0和>100的数据,统计个数,这部分数据对结果不会产生影响,因为中位数出现在99%的数据里面,即0-100这个范围内

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值