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();
 */
相关推荐
云烟成雨TD8 分钟前
Spring AI 1.x 系列【57】动态工具发现:Tool Search Tool
java·人工智能·spring
xiaofeichaichai15 分钟前
React Hooks
前端·javascript·react.js
zfoo-framework25 分钟前
[修改代码使用]codex官方app中使用中转(不需要cc-switch) 1.config.toml 2.sk方式登录
java
lizhihai_9928 分钟前
股市学习心得-AI 产业链核心标的梳理清单
大数据·服务器·人工智能·科技·学习
问心无愧051336 分钟前
ctf show web入门110
前端·笔记
拉拉肥_King41 分钟前
Vue 3 主题切换深度解析:从炫酷动画到零闪烁方案
前端·vue.js
excel43 分钟前
为什么 Pinia + localForage 持久化后,页面初始化拿不到数据?
前端
逍遥德44 分钟前
MQTT教程详解-05.SpringBoot集成mqtt client 性能分析
java·spring boot·spring·mt
雨雨雨雨雨别下啦1 小时前
vant介绍
前端
小小小小宇1 小时前
大模型失忆问题探讨
前端