双堆法求数据流的中位数

代码逻辑

这道题的关键在于如何在动态添加元素的过程中,快速找到中位数。

我们可以用一个大顶堆 (maxHeap)存储较小的一半元素,堆顶是这部分的最大值 和一个小顶堆 (minHeap)存储较大的一半元素,堆顶是这部分的最小值,这样的话,中位数就在两个堆的堆顶附近!

1.添加元素

添加新元素时, 如果大顶堆为空,或新元素 ≤ 大顶堆堆顶 → 放入大顶堆,否则 → 放入小顶堆。

如果两个堆的大小差为 2,就从元素多的堆中取出堆顶,放入另一个堆。

2.查找中位数

如果两个堆大小相等 → 中位数 = (大顶堆堆顶 + 小顶堆堆顶) / 2;

如果大小不等 → 中位数 = 元素多的那个堆的堆顶。

代码实现

java 复制代码
class MedianFinder {
    private PriorityQueue<Integer> maxHeap;  // 大顶堆,存储较小的一半
    private PriorityQueue<Integer> minHeap;  // 小顶堆,存储较大的一半
    
    public MedianFinder() {
        // Java的PriorityQueue默认是小顶堆,需要自定义比较器实现大顶堆
        maxHeap = new PriorityQueue<>((a, b) -> b - a);
        minHeap = new PriorityQueue<>((a, b) -> a - b);
    }
    
    public void addNum(int num) {
        // 决定新元素放入哪个堆
        if (maxHeap.isEmpty() || maxHeap.peek() >= num) {
            maxHeap.add(num);
        } else {
            minHeap.add(num);
        }
        // 调整两个堆的平衡
        balance();
    }
    
    public double findMedian() {
        if (maxHeap.size() == minHeap.size()) {
            // 偶数个元素,返回两个堆顶的平均值
            return (double) (maxHeap.peek() + minHeap.peek()) / 2;
        } else {
            // 奇数个元素,返回元素多的那个堆的堆顶
            return maxHeap.size() > minHeap.size() ? maxHeap.peek() : minHeap.peek();
        }
    }
    
    private void balance() {
        // 如果两个堆的大小差为2,需要调整
        if (Math.abs(maxHeap.size() - minHeap.size()) == 2) {
            if (maxHeap.size() > minHeap.size()) {
                minHeap.add(maxHeap.poll());
            } else {
                maxHeap.add(minHeap.poll());
            }
        }
    }
}
相关推荐
张萌杰1 天前
深度学习的基础知识(常见名词解释)
人工智能·深度学习·机器学习·1024程序员节
开开心心就好2 天前
免费无广告卸载工具,轻便安全适配全用户
linux·运维·服务器·网络·安全·启发式算法·1024程序员节
开开心心就好3 天前
图片格式转换工具,右键菜单一键转换简化
linux·运维·服务器·python·django·pdf·1024程序员节
徐子童5 天前
网络协议---TCP协议
网络·网络协议·tcp/ip·面试题·1024程序员节
扫地的小何尚7 天前
NVIDIA RTX PC开源AI工具升级:加速LLM和扩散模型的性能革命
人工智能·python·算法·开源·nvidia·1024程序员节
数据皮皮侠AI8 天前
上市公司股票名称相似度(1990-2025)
大数据·人工智能·笔记·区块链·能源·1024程序员节
开开心心就好8 天前
系统清理工具清理缓存日志,启动卸载管理
linux·运维·服务器·神经网络·cnn·pdf·1024程序员节
Evan东少11 天前
[踩坑]笔记本Ubuntu20.04+NvidiaRTX5060驱动+cuda+Pytorch+ROS/Python实现人脸追踪(环境准备)
1024程序员节
不爱编程的小陈12 天前
C/C++每日面试题
面试·职场和发展·1024程序员节
开开心心就好12 天前
右键菜单管理工具,添加程序自定义名称位置
linux·运维·服务器·ci/cd·docker·pdf·1024程序员节