CS-Wiki CS-Wiki
Home
知识体系总览
  • 数据结构与算法
  • 计算机网络
  • 操作系统
  • MySQL
  • Redis
  • 设计模式
  • Java 基础
  • Java 集合
  • Java 并发
  • Java 虚拟机
  • Spring
  • Kafka
  • 校招扫盲
  • 项目推荐
  • 唠唠嗑儿
  • 读书笔记
归档
GitHub (opens new window)
Home
知识体系总览
  • 数据结构与算法
  • 计算机网络
  • 操作系统
  • MySQL
  • Redis
  • 设计模式
  • Java 基础
  • Java 集合
  • Java 并发
  • Java 虚拟机
  • Spring
  • Kafka
  • 校招扫盲
  • 项目推荐
  • 唠唠嗑儿
  • 读书笔记
归档
GitHub (opens new window)
  • 刷题模板汇总
  • 一些刷题小技巧
  • 整数 and 位运算

  • 数组

  • 链表

  • 哈希表

  • 字符串

  • 栈

  • 队列

    • 队列理论基础
    • 用队列实现栈
    • 滑动窗口的平均值
    • 最近请求次数
    • 单调队列问题

    • 堆-优先级队列

      • 堆理论基础
      • 手写堆
      • 数据流的第 K 大数值
      • 数组中的第k大的数字
      • 前 K 个高频元素
      • 最小的 k 个数
      • 和最小的 k 个数对
      • 数据流中的中位数:对顶堆问题
        • 📃 题目描述
        • 🔔 解题思路
        • 💥 复杂度分析
  • 二叉树

  • 前缀树

  • 二分查找

  • 双指针法

  • 区间求和问题

  • 排序

  • 回溯算法

  • 贪心算法

  • 动态规划

  • 图

  • 数学

  • 自动机

  • 海量数据和空间限制

  • 05-数据结构与算法
  • 队列
  • 堆-优先级队列
小牛肉
2022-09-18
目录

数据流中的中位数:对顶堆问题

# 📃 题目描述

题目链接:剑指 Offer 41. 数据流中的中位数 (opens new window)

# 🔔 解题思路

我们用两个优先队列分别记录大于中位数的数(leftHeap,小根堆)和小于等于中位数的数(rightHeap,大根堆)

  • 当累计添加的数的数量为奇数时,leftHeap 中的数的数量比 rightHeap 多一个,此时中位数为 leftHeap 的队头
  • 当累计添加的数的数量为偶数时,两个优先队列中的数的数量相同,此时中位数为它们的队头的平均值。

当我们尝试添加一个数num 到数据结构中,我们需要分情况讨论:

  • num < leftHeap.peek():此时num 小于等于中位数,我们需要将该数添加到 leftHeap
  • num > rightHeap.peek():此时 num 大于中位数,我们需要将该数添加到 rightHeap 中

特别地,当累计添加的数的数量为 0 时,我们将 num 添加到 leftHeap 中

class MedianFinder {

    // 存储比中位数小的数(大根堆)
    private PriorityQueue<Integer> leftHeap;
    // 存储比中位数大的数(小根堆)
    private PriorityQueue<Integer> rightHeap;
    /** initialize your data structure here. */
    public MedianFinder() {
        leftHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
        rightHeap = new PriorityQueue<>();
    }
    
    public void addNum(int num) {
        // 新加入的数在中位数左边
        if (leftHeap.isEmpty() || num <= leftHeap.peek()) {
            leftHeap.offer(num);
            // 保证 leftHeap 数量 >= rightHeap 数量 + 1
            if (leftHeap.size() > rightHeap.size() + 1) {
                rightHeap.offer(leftHeap.poll());
            }
        }
        // 新加入的数在中位数右边
        else {
            rightHeap.offer(num);
            // 保证 leftHeap 数量 >= rightHeap 数量 + 1
            if (rightHeap.size() > leftHeap.size()) {
                leftHeap.offer(rightHeap.poll());
            }
        }
    }
    
    public double findMedian() {
        int count = leftHeap.size() + rightHeap.size();
        if (count % 2 == 0) {
            return (leftHeap.peek() + rightHeap.peek()) / 2.0;
        }

        return leftHeap.peek();
    }
}

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

# 💥 复杂度分析

  • 空间复杂度:
  • 时间复杂度:

🎁 公众号

各位小伙伴大家好呀,叫我小牛肉就行,目前在读东南大学硕士,上方扫码关注公众号「飞天小牛肉」,与你分享我的成长历程与技术感悟~

帮助小牛肉改善此页面 (opens new window)
Last Updated: 2023/02/16, 11:27:10
和最小的 k 个数对
二叉树理论基础

← 和最小的 k 个数对 二叉树理论基础→

最近更新
01
02
线上环境 CPU 使用率飙升如何快速排查?
03-05
03
面试官再跟你说中国没有根服务器,雪人计划让他了解下
02-23
更多文章>
Theme by Vdoing | Copyright © 2019-2023 飞天小牛肉 | 皖ICP备2022008966号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式