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

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]

解决思路:使用大小堆解决

注意,我们获取的中位数是有序列表中的中间的数(中间的单个元素或者两个元素均值)

解决的数据结构

我们使用两个堆来存储列表中的值,一个是大顶堆,一个是小顶堆

其中大顶堆的所有元素小于小顶堆的所有元素,并且我们需要维护大顶堆和小顶堆的大小,我们只允许大顶堆的大小等于小顶堆,或者比小顶堆小一个元素

如果是两个堆都为空的时候,先插入小顶堆,便于初始化,以便后面的元素能根据前面入堆的元素来判断应该进入哪一个堆

为什么这样的结构能解题

此时,如果我们要获取中位数,一共有两种情况

  • 大顶堆大小==小顶堆元素(此时列表大小为偶数),此时,大顶堆的堆顶元素(大于大顶堆的所有元素,小于小顶堆的所有元素)就相当于列表(2n)中的第n个元素,小顶堆的堆顶元素就相当于列表中的第n+1元素,也就是只要取两个堆顶的元素除以2即可
  • 大顶堆大小+1==小顶堆元素(列表大小为奇数2n+1),此时,大顶堆的元素个数为n+1,小顶堆的元素个数为n,大顶堆的堆顶元素位于列表中的第n+1位置(大于大顶堆中的所有n个元素元素,小于小顶堆的所有元素),所以大堆顶的堆顶元素就是中位数

解题代码如下

class MedianFinder {//使用两个优先级队列存储信息即可//小队列存储数值小的值,最大的放在堆顶,两个堆的数量差不能大于1(为了找中间值)//大队列存储数值大的值,最小的放在堆顶PriorityQueue<Integer> queueMin;PriorityQueue<Integer> queueMax;public MedianFinder() {queueMin=new PriorityQueue<>((a,b)->b-a);queueMax=new PriorityQueue<>((a,b)->a-b);}public void addNum(int num) {if(queueMin.isEmpty()||num<=queueMin.peek()){//如果要添加的元素小于小队列的最大值,就放入小队列queueMin.offer(num);if(queueMax.size()+1<queueMin.size()){queueMax.offer(queueMin.poll());}}else{queueMax.offer(num);//随后就是判断数量对不对if(queueMax.size()>queueMin.size()){queueMin.offer(queueMax.poll());}}}public double findMedian() {//尝试获取if(queueMin.size()>queueMax.size()){return queueMin.peek();}else{return (queueMin.peek()+queueMax.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.xdnf.cn/news/409861.html

相关文章:

  • PyTorch随机数控制全指南:从种子设置到状态管理
  • 【C++】”如虎添翼“:模板初阶
  • AI-Agent@spring ai概览
  • 动态IP技术赋能业务创新:解锁企业数字化转型新维度
  • 智表 ZCELL 插件快速入门指南(原创)
  • 【Redis】SDS结构
  • Redis的IO多路复用
  • 驾驭智能浪潮:AI SEO赋能的操作指南
  • Swift实战:如何优雅地从二叉搜索树中挑出最接近的K个值
  • C++ 中介者模式详解
  • 【嵌入式系统设计师(软考中级)】第三章:嵌入式系统软件基础知识——①软件及操作系统基础
  • 需求变更控制不严,如何防止项目范围扩大
  • CATIA高效工作指南——常规配置篇(二)
  • 黑马k8s(四)
  • windows防火墙
  • 2025年best好用的3dsmax插件和脚本
  • [Java实战]Spring Boot 整合 Swagger2 (十六)
  • 面试题:C++虚函数可以是内联函数吗?
  • 如何选择和实施PLM系统以提升企业效率?三品PLM系统:驱动企业效率跃升
  • 专业课复习笔记 9
  • 【记录nginx请求头参数丢失问题】
  • Android学习总结之布局篇
  • 《算法导论(第4版)》阅读笔记:p32-p38
  • Git常用操作
  • 测试文章标题01
  • 安装Hadoop并运行WordCount程序
  • 在IDEA中导入gitee项目
  • MySQL 8.0 OCP 1Z0-908 题目解析(1)
  • CSS3 伪类和使用场景
  • Matlab 列车纵向滑模二阶自抗扰算法和PID对比