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();
 */
相关推荐
五岳5 小时前
分库分表数据源ShardingSphereDataSource的Connection元数据误用问题分析
java·mysql·爬坑
带刺的坐椅5 小时前
迈向 MCP 集群化:Solon AI (支持 Java8+)在解决 MCP 服务可扩展性上的探索与实践
java·ai·llm·solon·mcp
鼠爷ねずみ6 小时前
SpringCloud前后端整体开发流程-以及技术总结文章实时更新中
java·数据库·后端·spring·spring cloud
A向前奔跑6 小时前
前端实现实现视频播放的方案和面试问题
前端·音视频
代码or搬砖6 小时前
String字符串
android·java·开发语言
十一.3666 小时前
131-133 定时器的应用
前端·javascript·html
xhxxx7 小时前
你的 AI 为什么总答非所问?缺的不是智商,是“记忆系统”
前端·langchain·llm
3824278278 小时前
python:输出JSON
前端·python·json
2503_928411568 小时前
12.22 wxml语法
开发语言·前端·javascript