当前位置: 首页 > news >正文

【Leetcode hot 100】295.数据流的中位数

问题链接

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

提示:

  • -10^5 <= num <= 10^5
  • 在调用 findMedian 之前,数据结构中至少有一个元素
  • 最多 5 * 10^4 次调用 addNumfindMedian

问题解答

题目分析

数据流的中位数问题核心挑战在于:数据流是动态添加的,需要频繁维护有序状态以快速计算中位数。若使用普通数组/列表,每次添加元素后排序的时间复杂度为 O(n log n),在最多 5*10^4 次调用的场景下会超时。

最优解决方案是使用 对顶堆(大顶堆 + 小顶堆),通过以下规则维护数据,确保 addNumfindMedian 操作的时间复杂度均为 O(log n)

  1. 大顶堆(maxHeap):存储数据流中较小的一半元素,堆顶为这部分的最大值(即中位数的候选之一)。
  2. 小顶堆(minHeap):存储数据流中较大的一半元素,堆顶为这部分的最小值(即中位数的候选之一)。
  3. 平衡规则
    • 元素总数为奇数时,确保大顶堆元素个数比小顶堆多 1(此时大顶堆堆顶即为中位数)。
    • 元素总数为偶数时,确保两个堆元素个数相等(此时中位数为两堆顶平均值)。
    • 始终保证大顶堆的堆顶 ≤ 小顶堆的堆顶(确保两堆元素有序划分)。

完整代码实现

import java.util.Collections;
import java.util.PriorityQueue;class MedianFinder {// 大顶堆:存储较小的一半元素(Java 默认是小顶堆,需用 Collections.reverseOrder() 反转)private final PriorityQueue<Integer> maxHeap;// 小顶堆:存储较大的一半元素private final PriorityQueue<Integer> minHeap;/*** 初始化 MedianFinder 对象* - maxHeap 初始化为大顶堆* - minHeap 初始化为默认小顶堆*/public MedianFinder() {maxHeap = new PriorityQueue<>(Collections.reverseOrder());minHeap = new PriorityQueue<>();}/*** 向数据流中添加元素 num* 核心逻辑:先按大小分配到对应堆,再调整堆的平衡*/public void addNum(int num) {// 1. 分配元素:若 num ≤ 大顶堆堆顶(或大顶堆为空),加入大顶堆;否则加入小顶堆if (maxHeap.isEmpty() || num <= maxHeap.peek()) {maxHeap.offer(num);} else {minHeap.offer(num);}// 2. 调整平衡:确保两堆元素个数差不超过 1,且大顶堆不小于小顶堆// 情况1:大顶堆元素过多(比小顶堆多 2 个),需转移堆顶到小顶堆if (maxHeap.size() > minHeap.size() + 1) {minHeap.offer(maxHeap.poll());}// 情况2:小顶堆元素过多(比大顶堆多 1 个),需转移堆顶到大顶堆else if (minHeap.size() > maxHeap.size()) {maxHeap.offer(minHeap.poll());}}/*** 计算并返回当前数据流的中位数*/public double findMedian() {// 元素总数为奇数:大顶堆元素多 1 个,堆顶即为中位数if (maxHeap.size() > minHeap.size()) {return maxHeap.peek();}// 元素总数为偶数:两堆顶平均值即为中位数(需转 double 避免整数除法)else {return (maxHeap.peek() + minHeap.peek()) / 2.0;}}// 测试代码(可直接在 LeetCode 中忽略,本地调试用)public static void main(String[] args) {MedianFinder medianFinder = new MedianFinder();medianFinder.addNum(1);    // 数据流:[1]medianFinder.addNum(2);    // 数据流:[1, 2]System.out.println(medianFinder.findMedian()); // 输出 1.5medianFinder.addNum(3);    // 数据流:[1, 2, 3]System.out.println(medianFinder.findMedian()); // 输出 2.0}
}/*** Your MedianFinder object will be instantiated and called as such:* MedianFinder obj = new MedianFinder();* obj.addNum(num);* double param_2 = obj.findMedian();*/

关键细节解释

  1. 堆的初始化

    • Java 的 PriorityQueue 默认是小顶堆,因此大顶堆需要通过 Collections.reverseOrder() 反转比较器。
    • 初始化时两堆均为空,后续添加元素时会自动建立堆结构。
  2. 元素分配逻辑

    • 优先将元素加入大顶堆的条件是“大顶堆为空”或“num ≤ 大顶堆堆顶”,确保大顶堆始终存储较小的一半元素。
    • 若 num 大于大顶堆堆顶,则加入小顶堆,确保小顶堆存储较大的一半元素。
  3. 平衡调整逻辑

    • 仅在添加元素后可能出现失衡(两堆大小差超过 1),此时通过“弹出多的堆的堆顶,加入另一堆”来修复平衡。
    • 调整后始终满足 maxHeap.size() == minHeap.size()maxHeap.size() == minHeap.size() + 1,保证中位数计算的正确性。
  4. 中位数计算

    • 奇数个元素:大顶堆多 1 个元素,堆顶就是排序后的中间元素。
    • 偶数个元素:两堆顶分别是排序后的中间两个元素,平均值即为中位数(除以 2.0 而非 2,避免整数除法导致的精度丢失)。

复杂度分析

操作时间复杂度空间复杂度
MedianFinder() 初始化O(1)O(1)
addNum(int num)O(log n)O(n)
findMedian()O(1)O(1)
  • 时间复杂度:堆的 offer()poll() 操作均为 O(log n)(n 为当前数据流元素总数),peek() 操作为 O(1),因此整体效率极高。
  • 空间复杂度:两堆共存储所有数据流元素,因此为 O(n)
http://www.dtcms.com/a/559124.html

相关文章:

  • 代理服务网站经济研究院网站建设方案
  • 一个空间只能放一个网站吗网站彩票代理怎么做
  • 毕业设计网站模板下载怎样建立门户网站
  • 如何做网站的伪静态页面做it行业招标网站
  • 做网站建站做问卷的网站有哪些
  • 企业品牌网站有哪些新乡网站建设公司
  • 软件测试大赛web测试-python【备赛3】
  • 如何去建立和设计一个公司网站不用下载微信在线登录
  • 建筑公司网站电工建网站用什么浏览器
  • 网站开发视频是存储的wordpress用户注册邮箱验证码
  • 阿里巴巴做网站的wordpress仿站pdf
  • 深圳手机网站设计网站规划和构成
  • html5怎么做网站老域名做网站好吗
  • 嘉兴seo公司网站微信同步wordpress
  • 织梦做中英文企业网站北京网站模板下载
  • 网站每年续费费用开小加工厂去哪接单子
  • 触屏网站建设网页设计素材书
  • 搜索网站大全厦门建设官网
  • 我设计的字符串
  • 遗传算法求解VRPTW问题MATLAB编程
  • 洛阳自助建站wordpress集成当面付
  • wordpress网站重定向张家界网站定制
  • 网站安全网站建设会议验收
  • 广州越秀建网站厦门互联网公司排名
  • 网站维护流程图做pop网站
  • 网站建设需要什么证书凤凰军事新闻
  • 怎样进行网站建设步骤作品集展示的网站源码
  • 网站开发如何设置视频株洲网站建设的公司
  • 美食健康网站的建设新网站建设代理商
  • 做企业的网站都要准备什么手续站长工具精华