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

server/2025/1/19 12:25:51/

问题背景

中位数 是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。

  • 例如 a r r = [ 2 , 3 , 4 ] arr = [2,3,4] arr=[2,3,4] 的中位数是 3 3 3
  • 例如 a r r = [ 2 , 3 ] arr = [2,3] arr=[2,3] 的中位数是 ( 2 + 3 ) / 2 = 2.5 (2 + 3) / 2 = 2.5 (2+3)/2=2.5
    实现 MedianFinder 类:
  • MedianFinder() 初始化 MedianFinder 对象。
  • void addNum(int num) 将数据流中的整数 n u m num num 添加到数据结构中。
  • double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 1 0 − 5 10 ^ {-5} 105 以内的答案将被接受。

数据约束

  • − 1 0 5 ≤ n u m ≤ 1 0 5 -10 ^ 5 \le num \le 10 ^ 5 105num105
  • 在调用 findMedian 之前,数据结构中至少有一个元素
  • 最多 5 ∗ 1 0 4 5 * 10 ^ 4 5104 次调用 addNumfindMedian

解题过程

这题分类讨论的思路比较麻烦,但是实现起来相当简洁,积累一下为好。
整体的结构是由一个最大堆和一个最小堆构成的,维护结构的过程中让这两个堆中的元素始终相等或最大堆中的元素比最小堆中的元素多,并且相差不能超过 1 1 1
最大堆中存储数据流中较小的那部分元素,最小堆中存储数据流中较大的那部分元素,这时中位数就可以根据两个堆顶元素方便地计算出来。数字数量不等时,中位数就是最大堆的堆顶元素;元素数量相等时,中位数就是两个堆顶元素的平均值。
以下 n u m num num 表示数据流中的新元素, m a x max max 表示最小堆中的最大值, m i n min min 表示最大堆中的最小值。

  • 如果两个堆中元素数量相等:
    • 当前元素较大的情况下, n u m num num 应被添加到最小堆中。这样一来就不符合定义了(最小堆比最大堆元素数量多 1 1 1),将 m a x max max 调整到最大堆中。
    • 当前元素较小的情况下, n u m num num 应被添加到最大堆中。这种情况同样可以先将元素添加到最小堆中,再将 m a x max max 调整到最大堆中。
  • 如果两个堆中元素数量不等:
    • 当前元素较小的情况下, n u m num num 应被添加到最大堆中。这样一来就不符合定义了(最大堆比最小堆元素数量多 2 2 2),将 m i n min min 调整到最小堆中。
    • 当前元素较大的情况下, n u m num num 应被添加到最小堆中。这种情况同样可以先将元素添加到最大堆中,再将 m i n min min 调整到最小堆中。

实际写的时候,只要搞清楚什么情况下该怎么倒腾元素就不会出错。
Java 中的类默认自带一个空参构造器,所以实际上 MedianFinder() 可以不写。

具体实现

class MedianFinder {private final PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);private final PriorityQueue<Integer> minHeap = new PriorityQueue<>();public void addNum(int num) {if(maxHeap.size() == minHeap.size()) {minHeap.offer(num);maxHeap.offer(minHeap.poll());} else {maxHeap.offer(num);minHeap.offer(maxHeap.poll());}}public double findMedian() {if(maxHeap.size() > minHeap.size()) {return maxHeap.peek();}return (minHeap.peek() + maxHeap.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();*/

http://www.ppmy.cn/server/159624.html

相关文章

网络编程 | UDP广播通信

1、什么是广播 在上一篇博客文章中已经对UDP进行了详细的说明介绍及如何编程实现。本文将接着上一文的内容&#xff0c;在其基础上&#xff0c;对UDP的知识体系进一步深入的讲解。 网络编程 | UDP套接字通信及编程实现经验教程-CSDN博客 例子&#xff1a;在一些中小学的操场中&…

【Linux】线程全解:概念、操作、互斥与同步机制、线程池实现

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长&#xff0c;行则将至 目录 &#x1f4da;一、线程概念 &#x1f4d6; 回顾进程 &#x1f4d6; 引入线程 &#x1f4d6; 总结 &a…

牛客---mysql

查找学校是北大的学生信息_牛客题霸_牛客网 题目&#xff1a;现在运营想要筛选出所有北京大学的学生进行用户调研&#xff0c;请你从用户信息表中取出满足条件的数据&#xff0c;结果返回设备id和学校。 示例&#xff1a;user_profile iddevice_idgenderageuniversityprovinc…

精选了几道MySQL的大厂面试题,被提问的几率很高!

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

vue 学习笔记 - 创建第一个项目 idea

1、安装Vue CLI 查看npm版本号 &#xff08;可跳过&#xff09; % npm -v 11.0.0安装Vue CLI % npm install -g vue/cli2、创建项目 进入工程文件目录 % cd /Users/ruizhifeng/work/aina-client查看vue 版本号 &#xff08;可跳过&#xff09; % vue --version vue/cli 5…

ORB-SLAM3 RGBD摄像头

一、所需的环境 python2.7、Opencv3.2、Pangolin0.5、eigen3.3.1 Ubuntu18.04、ros版本&#xff1a;melodic 二、安装astro pro plus驱动 1、安装环境所需要依赖 sudo apt-get install ros-melodic-serial ros-melodic-bfl ros-melodic-mbf-msgs ros melodic-pointcloud-t…

Excel 技巧10 - 如何检查输入重复数据(★★)

本文讲了如何在Excel中通过COUNTIF来检查输入重复数据。 当输入重复数据时&#xff0c;显示错误提示。 1&#xff0c;通过COUNTIF来检查输入重复数据 比如下面是想检查不要输入重复的学号。 选中C列&#xff0c;点 Menu > 数据 > 数据验证 在数据验证页面&#xff0c…

SpringBoot的Bean-中级-作用域

5个作用域&#xff1a; 初级演示的是第一种默认的singleton&#xff1a;SpringBoot的Bean-初级获取bean对象-CSDN博客 中级-1&#xff1a;Lazy注解使其在使用的时候再实例化 中级-2&#xff1a;Scope("prototype")使其每次需要注入的时候都实例化新的对象 测试程序&…