[LeetCode][295]数据流的中位数——巧妙利用大顶堆和小顶堆排序

295. 数据流的中位数

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

例如 arr = [2,3,4] 的中位数是 3 。 例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5 。
实现 MedianFinder 类,包括以下方法:

  • MedianFinder(): 初始化 MedianFinder 对象
  • addNum(int num): 将数据流中的整数 num 添加到数据结构中
  • 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();
// 返回 2.0

提示:
-105 <= num <= 105 在调用 findMedian 之前,数据结构中至少有一个元素 最多 5 * 10^4 次调用 addNum 和 findMedian

思考

  • 这题要求的数据结构只有插入没有弹出
  • 从这道题要求的时间看,插入和寻找中位数的时间复杂度都应该选择比较低的
  • 如果要在插入元素后快速得到中位数,那么这种数据结构应该是有序的,否则遍历得到中位数的时间复杂度将是O(n)
  • 对有序数据结构,插入后仍然保持有序,可以想到使用二分插入,那么二分寻找插入位置的时间复杂度就是O(logn)
  • 如果使用数组来实现二分插入,虽然二分寻找插入位置的时间复杂度为O(logn),但是由于插入后数据需要后挪,移动的时间复杂度是O(n)
  • 堆的插入时间就只有O(logn),且能以常数时间找到最小或者最大的值(小顶堆和大顶堆),但是这道题是要求查找中位数,而堆并不能实现中位数的常数寻找
  • 但是中位数的特性是,在一个升序序列上,中位数左边的数字都比它小,右边的数字都比他大。那么可以将比中位数小的元素放入大顶堆,比中位数大的元素放入小顶堆,这样就可以将中位数暴露在堆顶,插入元素时,选择放入其中一个堆,此时堆顶(中位数)可能会更新,将更新后的中位数也执行插入即可

解法:大顶堆+小顶堆

  • 设大顶堆为A,小顶堆为B
  • 假设大顶堆A 保存较小的一半以及中位数,而小顶堆B 保存较大的一半
  • 那么当元素总个数为奇数时,大顶堆A 的元素个数就比小顶堆多 1,且中位数为大顶堆A 的顶
  • 当元素个数为偶数时,两个堆的元素数量一致,中位数为两个堆堆顶的平均值

  • 搞定了中位数的查找,接下来就解决插入问题
  • 当当前元素总数为偶数时,两个堆的元素数量都一致,那么如果此时要新增一个元素,按照上面说的:假设大顶堆A 保存较小的一半以及中位数,则应该把这个元素插入大顶堆A中,这样元素总数为奇数后中位数就是大顶堆A 的堆顶
  • 但是新增的元素可能并不属于较小的那一半,直接插入大顶堆A 会破坏 A 的结构,所以需要将其先放入小顶堆B 中清洗一下。如果新增的元素确实属于较小的那一半,那么在放入小顶堆后会被暴露在堆顶,此时将 B堆顶插入大顶堆A 即可;如果新增的元素属于较大的那一半,那么放入小顶堆后并不会改变小顶堆的堆顶元素,但是为了保持小顶堆B 的元素个数(因为本来是要向大顶堆A 中插入元素的),则需要把大顶堆B 的堆顶元素插入小顶堆A 中
  • 以此类推,当当前元素总数为奇数时,小顶堆A 元素比大顶堆元素多一个,新增元素就要插入大顶堆B 中,但是也需要放入小顶堆A 中进行数据清洗后,再找出合适的元素插入大顶堆B

class MedianFinder {
    //设大顶堆的元素比小顶堆多0或1个,也就是有奇数个元素时大顶堆堆顶即为中位数
    priority_queue<int, vector<int>, greater<int>> minHeap;//小顶堆
    priority_queue<int> maxHeap;//大顶堆
    int n=0;//总元素个数
public:
    MedianFinder() {

    }
    
    void addNum(int num) {
        if(n%2){//元素个数为奇数,最终要在小顶堆中新增元素
            maxHeap.push(num);//先放入大顶堆中清洗数据
            minHeap.push(maxHeap.top());//再把大顶堆堆顶存入小顶堆中
            maxHeap.pop();
        }
        else{//元素个数为偶数
            minHeap.push(num);
            maxHeap.push(minHeap.top());
            minHeap.pop();
        }
        ++n;
    }
    
    double findMedian() {
        if(n%2) return maxHeap.top();
        else return (maxHeap.top()+minHeap.top())/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.mfbz.cn/a/443085.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IntelliJ IDEA 2020.2.4试用方法

打开idea&#xff0c;准备好ide-eval-resetter压缩包。 将准备好的压缩包拖入idea中 选中弹窗中的自动重置选项&#xff0c;并点击重置 查看免费试用时长

[数据集][目标检测]变电站缺陷检测数据集VOC+YOLO格式8307张17类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8307 标注数量(xml文件个数)&#xff1a;8307 标注数量(txt文件个数)&#xff1a;8307 标注…

汽车大灯汽车尾灯破裂裂纹破损破洞掉角崩角等问题能修复吗?修复后需要注意什么?

汽车灯罩破损修复后&#xff0c;车主需要注意以下几点&#xff1a; 检查修复效果&#xff1a;修复完成后&#xff0c;车主应该仔细检查灯罩的修复效果&#xff0c;确保破损部分已经被填补并恢复原有的透明度和光泽。如果修复效果不理想&#xff0c;需要及时联系维修店进行处理…

问题:前端获取long型数值精度丢失,后面几位都为0

文章目录 问题分析解决 问题 通过接口获取到的数据和 Postman 获取到的数据不一样&#xff0c;仔细看 data 的第17位之后 分析 该字段类型是long类型问题&#xff1a;前端接收到数据后&#xff0c;发现精度丢失&#xff0c;当返回的结果超过17位的时候&#xff0c;后面的全…

什么是工业级物联网智能网关?如何远程控制PLC?

在这个信息爆炸的时代&#xff0c;物联网技术已经逐渐渗透到我们生活的方方面面&#xff0c;而工业级物联网智能网关作为连接工业设备和云端的重要桥梁&#xff0c;更是引领着工业4.0时代的浪潮。那么&#xff0c;究竟什么是工业级物联网智能网关呢&#xff1f;今天&#xff0c…

git删除comimit提交的记录

文章目录 本地的删除远程同步修改上次提交更多详情阅读 本地的删除 例如我的提交历史如下 commit 58211e7a5da5e74171e90d8b90b2f00881a48d3a Author: test <test36nu.com> Date: Fri Sep 22 20:55:38 2017 0800add d.txtcommit 0fb295fe0e0276f0c81df61c4fd853b7a00…

详解DNS服务

华子目录 概述产生原因作用连接方式 因特网的域名结构拓扑分类域名服务器类型划分 DNS域名解析过程分类解析图图过程分析注意 搭建DNS域名解析服务器概述安装软件bind服务中的三个关键文件 配置文件分析主配置文件共4部分组成区域配置文件作用区域配置文件示例分析正向解析反向…

STM32代码调试时遇到的一些error和warning

持续更新 ERROR WARNING 1.Note: object file renamed from “xxx.o“ to “xxx_1.o“ 出现下面这些warning可能的原因&#xff1a; &#xff08;1&#xff09;没有将头文件加入到main.c中&#xff0c;检查一下在编译。 &#xff08;2&#xff09;修改源文件路径的时候忘记…

python学习the sixth day

python函数进阶 一、函数多返回值 二、函数的多种参数使用 1.位置参数 2.关键字参数 3.缺省参数 设置默认值&#xff0c;必须放在最后面 4.不定长参数 4.总结 三、匿名函数 1.函数作为参数传递 这是计算逻辑的传递&#xff0c;而非数据的传递 2.lambda匿名函数 python文件操…

【电路笔记】-PNP晶体管

PNP晶体管 文章目录 PNP晶体管1、概述2、PNP晶体管电路示例3、PNP晶体管识别1、概述 PNP 晶体管与我们在上一篇教程中看到的 NPN 晶体管器件完全相反。 在这种类型的 PNP 晶体管结构中,两个互连的二极管相对于之前的 NPN 晶体管是相反的。 这会产生正-负-正类型的配置,箭头…

JAVA实战开源项目:智能停车场管理系统(Vue+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容A. 车主端功能B. 停车工作人员功能C. 系统管理员功能1. 停车位模块2. 车辆模块3. 停车记录模块4. IC卡模块5. IC卡挂失模块 三、界面展示3.1 登录注册3.2 车辆模块3.3 停车位模块3.4 停车数据模块3.5 IC卡档案模块3.6 IC卡挂…

Android Studio下载gradle超时问题解决

方法一 1. 配置根目录的setting.gradle.kts文件 pluginManagement {repositories {maven { urluri ("https://www.jitpack.io")}maven { urluri ("https://maven.aliyun.com/repository/releases")}maven { urluri ("https://maven.aliyun.com/repos…

基于springboot的家庭装修报价系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 SpringBoot框架 3 1.2 ECharts 3 1.3 Vue框架 3 1.4 Bootstrap框架 3 1.5 JQuery技术 4 1.6 Ajax技术 4 1.7 本章小结 4 2 系统分析 5 2.1 需求分析 5 2.2 非功能需求 7 2.3 本章小结 8 3 系统设计 9 3.1 系统总体设计 9 …

Python学习日记之学习turtle库(上 篇)

一、初步认识turtle库 turtle 库是 Python 语言中一个很流行的绘制图像的函数库&#xff0c;想象一个小乌龟&#xff0c;在一个横 轴为 x、纵轴为 y 的坐标系原点&#xff0c;(0,0)位置开始&#xff0c;它根据一组函数指令的控制&#xff0c;在这个平面 坐标系中移动&#xff0…

ubuntu 运行opencv_sample遇到的问题

首先我遇到的问题就是摄像头连接不上 勾选最后一个 然后是 usb接口问题 点击虚拟机设置 我的是改为 3 就可以啦

TensorRT是什么,有什么作用,如何使用

TensorRT 是由 NVIDIA 提供的一个高性能深度学习推理&#xff08;inference&#xff09;引擎。它专为生产环境中的部署而设计&#xff0c;用于提高在 NVIDIA GPU 上运行的深度学习模型的推理速度和效率。以下是关于 TensorRT 的详细介绍&#xff1a; TensorRT 是 NVIDIA 推出的…

Facebook广告必坑指南

不明确的目标&#xff1a; 在开始广告活动之前&#xff0c;确保你清楚自己的广告目标。是想提高品牌知名度、促进销售、还是增加网站流量&#xff1f;明确的目标有助于指导广告内容和策略。 忽视目标受众定位&#xff1a; 确定你的目标受众是关键的。使用Facebook广告管理工具…

【JavaEE进阶】 @Transactional详解

文章目录 &#x1f343;前言&#x1f332;rollbackFor&#xff08;异常回滚属性&#xff09;&#x1f384;事务隔离级别&#x1f6a9;MySQL事务隔离级别&#x1f6a9;Spring事务隔离级别 &#x1f38b;Spring事务传播机制&#x1f6a9;什么是事务传播机制&#x1f6a9;事务有哪…

防御保护----IPSEC VPPN实验

实验拓扑&#xff1a; 实验背景&#xff1a;FW1和FW2是双机热备的状态。 实验要求&#xff1a;在FW和FW3之间建立一条IPSEC通道&#xff0c;保证10.0.2.0/24网段可以正常访问到192.168.1.0/24 IPSEC VPPN实验配置&#xff08;由于是双机热备状态&#xff0c;所以FW1和FW2只需要…

ARM中汇编语言的学习(加法、乘法、除法、左移、右移、按位与等多种命令操作实例以及ARM的 N、Z、C、V 标志位的解释)

汇编概述 汇编需要学习的大致框架如下&#xff1a; 汇编中的符号 1.指令&#xff1b;能够北嘁肷梢惶?2bit机器码&#xff0c;并且能够被cpui识别和执行 2.伪指令&#xff1a;本身不是指令&#xff0c;编译器可以将其替换成若干条指令 3.伪操作&#xff1a;不会生成指令…