295. 数据流的中位数【困难】

中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。

  • 例如 arr = [2,3,4] 的中位数是 3 。
  • 例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5 。

实现 MedianFinder 类:

  • MedianFinder() 初始化 MedianFinder 对象。

  • void addNum(int num) 将数据流中的整数 num 添加到数据结构中。

  • double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。

示例 1:

复制代码
输入
["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"]
[[], [1], [2], [], [3], []]
输出
[null, null, null, 1.5, null, 2.0]

解释
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1);    // arr = [1]
medianFinder.addNum(2);    // arr = [1, 2]
medianFinder.findMedian(); // 返回 1.5 ((1 + 2) / 2)
medianFinder.addNum(3);    // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0

一、双堆法

思路:

用两个堆来分别存一半的较小和较大的数,大顶堆允许比小顶堆最多多一个元素。

小顶堆存较大一半的数,堆顶是较大数中的最小值。

大顶堆存较小一半多数,堆顶是较小数中的最大值。

这样中位数就可以通过取两个堆的堆顶元素来计算获得。

通过判断元素和堆顶元素的大小来添加进不同的堆,那怎么调整两个堆是元素数量呢?

直接比较,如果小顶堆的元素数量比大顶堆多了1(只会多1,因为每次插入元素都会判断),就直接把小顶堆的堆顶元素移除并加到大顶堆中。

时间复杂度O(log n)

代码:

java 复制代码
class MedianFinder {
    private PriorityQueue<Integer> minHeap;
    private PriorityQueue<Integer> maxHeap;

    public MedianFinder() {
        minHeap = new PriorityQueue<>();
        maxHeap = new PriorityQueue<>(Collections.reverseOrder());
    }
    
    public void addNum(int num) {
        if(!maxHeap.isEmpty() && num < maxHeap.peek()){
            maxHeap.offer(num);
        }else{
            minHeap.offer(num);
        }

        // 平衡两个堆的数量
        if(maxHeap.size() > minHeap.size() + 1){
            minHeap.offer(maxHeap.poll());
        }else if(minHeap.size() > maxHeap.size()){
            maxHeap.offer(minHeap.poll());
        }

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

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */
相关推荐
Java_2017_csdn4 小时前
OFC、ERP、OMS、WMS、TMS 对比-详解
java
网硕互联的小客服11 小时前
Linux服务器磁盘应该如何合理分区?
linux·运维·服务器
FungLeo11 小时前
成为全栈·React 管理后台篇·总复盘:从“接口能调通”到“后台值得使用”
前端·react.js·前端框架·项目复盘·成为全栈
EatFan12 小时前
Spring Boot 4 落地观察:从 yudao-cloud、matecloud、JPower 看国产脚手架的升级路线与迁移清单
java·spring boot·后端·spring cloud·微服务·后端开发·jdk 21
lisanmengmeng12 小时前
nacos nrpe 监控机及被监控机部署
服务器·nacos·nagios·nrpe
Maiko Star12 小时前
* LangChain 提示词模板详解:ChatPromptTemplate 的使用与高级特性
java·人工智能·langchain
Csvn13 小时前
并发模式:让渲染学会排队、插队和让路
前端
可乐鸡翅yeah_13 小时前
新手梳理:M3U8 线上问题,哪些是前端锅,哪些是后端锅
前端·ios·音视频·实时音视频·m3u8·音视频在线播放
Flynt13 小时前
Linear 用 1000 个 PR 换掉 styled-components,我写了 200 个按钮,把这笔账复现了一遍
前端·css·preact
2301_8084143813 小时前
Linux中动静态库的理解
linux·运维·服务器