算法通关村第十四关—数据流的中位数(黄金)

数据流中中位数的问题

 LeetCode295,中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如:2,3,4的中位数是3

2,3的中位数是(2+3)/2=2.5

实现 MedianFinder 类:

  • MedianFinder() 初始化 MedianFinder 对象。
  • void addNum(int num) 将数据流中的整数 num 添加到数据结构中。
  • double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。

 分析这是一道比较难的题目了,如果没专门学过,很难在面试时想到。

 中位数的题,我们一般都可以用大顶堆+小顶堆来求解,下面我们通过直观的例子解释一下怎么做。

小顶堆(minHeap):存储所有元素中较大的一半,堆顶存储的是其中最小的数。

大顶堆(maxHeap):存储所有元素中较小的一半,堆顶存储的是其中最大的数。

 相当于,把所有元素分成了大和小两半,而我们计算中位数,只需要大的那半的最小值和小的那半的最大值即可。比如,我们依次添加1,2,3,4,5,砍成两半之后为1,23,4,5,我们只要能快速的找到2和3即可。

 下面看看使用两个堆它们是怎么变化的:

1.添加1,进入到minHeap中,中位数为1:

2.添加2,它比minHeap堆顶元素1大,进入minHeap,同时,minHeap中元素超过了所有元素总和的一半,所以,要平衡一下,分一个给maxHeap,中位数为(1+2)/2.0=1.5:

添加3,它比minHeap堆顶元素2大,进入minHeap,中位数为2:

添加4,它比minHeap堆顶元素2大,进入minHeap,同时,minHeap中元素超过了所有元素总和的一半,所以,要平衡一下,分一个给maxHeap,中位数为(2+3)/2.0=2.5:

5.添加5,它比minHeap堆J顶元素3大,进入minHeap,中位数为3:

 Java中的堆(即优先级队列)是使用完全二叉树实现的,我们这里的图也是以完全二叉树为例。理解了上述的过程,看代码就比较简单了

 代码如下

java 复制代码
class MedianFinder {
    PriorityQueue<Integer> queleft;
    PriorityQueue<Integer> queright;

    public MedianFinder() {
        queleft = new PriorityQueue<Integer>((a, b) -> (b - a));//中位数左边是大顶堆
        queright = new PriorityQueue();//中位数右边是小顶堆
    }
    
    public void addNum(int num) { //添加元素
        if(queleft.isEmpty() || num <= queleft.peek()){
            queleft.offer(num);
            if(queleft.size() > queright.size() + 1){ //queleft最多比queright多一个元素
                queright.offer(queleft.poll());
            }
        }
        else{
            queright.offer(num);
            if(queright.size() > queleft.size()){
                queleft.offer(queright.poll());
            }
        }
    }
    
    public double findMedian() { 
        if(queleft.size() > queright.size()){//奇数情况
            return 1.0 * queleft.peek();
        }
        else return (queleft.peek() + queright.peek()) / 2.0;
    }
}
相关推荐
keyipatience20 分钟前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
我的xiaodoujiao25 分钟前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
战族狼魂41 分钟前
高频面试题精选:分治与AI Agent架构
人工智能·算法·大模型·大语言模型
weixin_408099671 小时前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能
李剑一1 小时前
你用过网易的将军令嘛?它底层实现账号保护的原理相当简单粗暴
算法
Scott9999HH1 小时前
告别流量波动玄学!从法拉第电磁定律到底层 C/C++ 流量累积算法,深度解密工业级电磁流量计选型与开发
c语言·c++·算法
爱喝水的鱼丶1 小时前
SAP-ABAP:ALV通用封装实践——搭建可复用的ALV开发工具类,减少80%重复代码
开发语言·性能优化·sap·abap·erp·alv
钱六两1 小时前
#3、SpringAI 接入deepSeek大模型(喂饭版)
java·spring boot·ai编程
脱胎换骨-军哥1 小时前
C++/Rust无缝互操作:混合系统新常态
开发语言·c++·rust
songroom2 小时前
Kimi K3:Rust封装XTP接口详细教程实践
开发语言·后端·rust