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

剑指 Offer 41. 数据流中的中位数

题目

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

例如,[2,3,4] 的中位数是 3, [2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

void addNum(int num) - 从数据流中添加一个整数到数据结构中。 double findMedian() -返回目前所有元素的中位数。

在这里插入图片描述

思路

优先队列 / 堆

给定一长度为 N 的无序数组,其中位数的计算方法:首先对数组执行排序(使用 O(Nlog⁡N)时间),然后返回中间元素即可(使用 O(1) 时间)

本题可以根据上述思想,将数据流保存在一个列表中,并在添加元素时保持数组有序,给定一长度为 N 的无序数组,其中位数的计算方法:首先对数组执行排序(使用 O(Nlog⁡N) 时间),然后返回中间元素即可(使用 O(1)时间)

借助 进行优化时间复杂度

建立两个堆,一个小顶堆A,一个大顶堆B,各自保存列表的一半元素 ,其中:

  • A保存较大的一半,长度为N/2或者(N+1)/2
  • B保存较小的一半,长度为N/2或者(N+1)/2

最后,中位数可以仅根据A,B的堆顶元素计算得到:
在这里插入图片描述
举个例子:数据流 [1,2,3,4,5,6,7,8]

如图所示,则[1,2,3,4]保存在大顶堆B,且堆顶元素为4(因为大顶堆堆顶元素最大),然后[5,6,7,8]保存在小顶堆A,且堆顶元素为5(因为小顶堆堆顶元素最小),这也是为什么大顶堆保存较小的一半,小顶堆保存较大的一半,为了就是可以通过A,B的堆顶元素求中位数

算法流程:

设元素总数为 N = m + n ,其中 mn 分别为 AB 中的元素个数

  • addNum(num) 函数:添加元素,
    (1)当 m=n(即 N 为 偶数):需向 A 添加一个元素,即AB中元素个数相等时,优先往A中先加元素。实现方法:将新元素 num插入至 B ,再将 B 堆顶元素插入至 A这是为了始终保证A中存较大的一半,B中存较小的一半,因为num可能属于较小的一半,即B中的元素,所以要先加入B,再将B堆顶元素插入A);

举个例子,A中加入1需要先加入B中,然后将B的堆顶元素3加入A
在这里插入图片描述
在这里插入图片描述

(2)当 m≠n(即 N 为 奇数):需向 B 添加一个元素,此时情况即为AB多一个元素。实现方法:将新元素 num 插入至 A ,再将A 堆顶元素插入至 B (同理,为了始终保证A中存较大的一半,B中存较小的一半,要先加入A,再将A的堆顶元素插入B,因为num可能属于较大的一般分,即属于A的元素);

举个例子,B中加入6需要先加入A中,然后将A的堆顶元素3加入B
在这里插入图片描述
在这里插入图片描述

  • findMedian() 函数:找中位数
    (1)当 m=nN 为 偶数):则中位数为 ( A 的堆顶元素 + B 的堆顶元素 ) / 2
    (2)当 m≠nN 为 奇数):则中位数为 A 的堆顶元素。

复杂度分析:

  • 时间复杂度:
    (1)查找中位数 O(1) : 获取堆顶元素使用 O(1) 时间;
    (2)添加数字 O(log⁡N) : 堆的插入和弹出操作使用 O(log⁡N)时间
  • 空间复杂度O(N):其中 N 为数据流中的元素数量,小顶堆 A 和大顶堆 B 最多同时保存 N个元素。

java代码如下:

class MedianFinder{Queue<Integer> A,B;public MedianFinder() {A = new PriorityQueue<>();//java默认小顶堆,保存较大的一半B = new PriorityQueue<>((x,y) -> (y - x));//使用降序定义大顶堆(因为大顶堆堆顶元素最大,所以是降序,但是用于升序排序,因为每次出堆顶元素是最大的),保存较小的一半}public void addNum(int num){if(A.size() != B.size()){//如果A,B元素个数不相等,则往B中添加元素//但是为了始终保证A中存较大的一半,B中存较小的一半A.add(num);//要先往A中加B.add(A.poll());//然后再将A的堆顶元素加入B} else {//如果A,B元素个数相等,则往A中添加元素//同理为了始终保证A中存较大的一半,B中存较小的一半B.add(num);A.add(B.poll());//要先往B中加//然后再将B的堆顶元素加入A}}public double findMedian(){return A.size() != B.size() ? A.peek() : (A.peek() + B.peek()) / 2.0;}
}

相关文章:

剑指 Offer 41. 数据流中的中位数

题目 如何得到一个数据流中的中位数&#xff1f;如果从数据流中读出奇数个数值&#xff0c;那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值&#xff0c;那么中位数就是所有数值排序之后中间两个数的平均值。 例如&#xff0c;[2,3,4] 的中位数是…...

分布式架构下,Session共享有什么方案?

分布式架构下&#xff0c;Session共享有什么方案&#xff1f; 1.不要有Session&#xff1a;但是确实在某些场景下&#xff0c;是可以没有session的&#xff0c;其实在很多借口类系统当中&#xff0c;都提倡【API无状态服务】&#xff1b; 也就是每一次的接口访问&#xff0c;都…...

瀚博半导体载天VA1 加速卡安装过程

背景&#xff1a; 想用 瀚博半导体载天VA1 加速卡 代替 NVIDIA 显卡跑深度学习模型 感谢瀚博的周工帮助解答。 正文&#xff1a; 小心拔出 NVIDIA 显卡&#xff0c;在PCIe 接口插上瀚博半导体载天VA1加速卡&#xff0c;如图&#xff1a; 这时显示屏连接主板的集成显卡 卸载…...

服务降级和熔断机制

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;服务降级和熔断机制 ✅创作者&#xff1a;林在闪闪发光 ⏰预计时间&#xff1a;30分钟 &#x1f389;个人主页&#xff1a;林在闪闪发光的个人主页 &#x1f341;林在闪闪发光的个人社区&#xff0c;欢迎你的加入: 林在闪闪…...

史上最全最详细的Instagram 欢迎消息引流及示例

史上最全最详细的Instagram 欢迎消息引流及示例&#xff01;关键词&#xff1a; Instagram 欢迎消息SaleSmartly&#xff08;ss客服&#xff09; 寻找 Instagram 欢迎消息示例&#xff0c;您可以用于您的业务。在本文中&#xff0c;我们将介绍Instagram欢迎消息的基础知识和好处…...

MDB 5 UI-KIT Bootstrap 5 最新版放送

顶级开源 UI 套件&#xff0c;Bootstrap v5 和 v4 的材料设计&#xff0c;jQuery 版本&#xff0c;数百个优质组件和模板&#xff0c;所有一致的&#xff0c;有据可查的&#xff0c;可靠的超级简单&#xff0c;1分钟安装简单的主题和定制 受到超过 3,000,000 名开发人员和设计师…...

做专家型服务者,尚博信助力企业数字化转型跑出“加速度” | 爱分析调研

01 从技术应用到业务重构&#xff0c;数字化市场呼唤专家型厂商 企业数字化转型是一个长期且系统性的变革过程。伴随着企业从信息化建设转向业务的数字化重构&#xff0c;市场对数字化厂商的能力要求也在升级。 早期的信息化建设主要是从技术视角切入&#xff0c;采用局部需求…...

CSS 重新认识 !important 肯定有你不知道的

重新认识 !important 影响级联规则 与 animation 和 transition 的关系级联层cascade layer内联样式!important 与权重 !important 与简写属性!important 与自定义变量!important 最佳实践 在开始之前, 先来规范一下文中的用于, 首先看 W3C 中关于 CSS 的一些术语定义吧. 下图…...

android 12添加系统字体并且设置为默认字体

需求&#xff1a;在11.0 12.0系统定制化开发中&#xff0c;在产品定制中&#xff0c;有产品需求对于系统字体风格不太满意&#xff0c;所以想要更换系统的默认字体&#xff0c;对于系统字体的修改也是常有的功能&#xff0c;而系统默认也支持增加字体&#xff0c;所以就来添加楷…...

LeetCode刷题系列 -- 1094. 拼车

车上最初有 capacity 个空座位。车 只能 向一个方向行驶&#xff08;也就是说&#xff0c;不允许掉头或改变方向&#xff09;给定整数 capacity 和一个数组 trips , trip[i] [numPassengersi, fromi, toi] 表示第 i 次旅行有 numPassengersi 乘客&#xff0c;接他们和放他们的…...

二叉查找树的应用 —— K模型和KV模型

文章目录前言1. K模型2. KV模型&#x1f351; 构建KV模型的树&#x1f351; 英汉词典&#x1f351; 统计水果出现的次数3. 总结前言 在上一篇文章中&#xff0c;我们进行了二叉查找树的实现&#xff08;文章链接&#xff09;&#xff0c;那么今天主要探讨一下二叉查找树的应用…...

深度学习实战(11):使用多层感知器分类器对手写数字进行分类

使用多层感知器分类器对手写数字进行分类 1.简介 1.1 什么是多层感知器&#xff08;MLP&#xff09;&#xff1f; MLP 是一种监督机器学习 (ML) 算法&#xff0c;属于前馈人工神经网络 [1] 类。该算法本质上是在数据上进行训练以学习函数。给定一组特征和一个目标变量&#x…...

ThingsBoard-警报

1、使用 IoT 设备警报 ThingsBoard 提供了创建和管理与您的实体相关的警报的能力:设备、资产、客户等。例如,您可以将 ThingsBoard 配置为在温度传感器读数高于某个阈值时自动创建警报。当然,这是一个非常简化的案例,实际场景可能要复杂得多。 2、主要概念 下面让我们回…...

如何去阅读源码,我总结了18条心法

在聊如何去阅读源码之前&#xff0c;先来简单说一下为什么要去阅读源码&#xff0c;大致可分为以下几点原因&#xff1a;最直接的原因&#xff0c;就是面试需要&#xff0c;面试喜欢问源码&#xff0c;读完源码才可以跟面试官battle提升自己的编程水平&#xff0c;学习编程思想…...

排序:归并排序

一、归并 li[2,4,5,7,//1,3,6,8]#归并的前提是必须两部分排好序 def merge(li,low,mid,high):ilowjmid1ltmp[]while i<mid and j<high: #只要左右两边都有数if li[i]<li[j]:ltmp.append(li[i])i1else:ltmp.append(li[j])j1#while执行完&#xff0c;肯定有一部分没数…...

Allegro172版本线到铜皮不按照设定值避让的原因和解决办法

Allegro172版本线到铜皮不按照设定值避让的原因和解决办法 用Allegro做PCB设计的时候,有时会单独给某块铜皮附上线到铜皮额外再增加一个数值,如下图 在规则的基础上,额外再避让10mil 规则避让line到铜皮10.02mil 额外设置多避让10mil,避让的结果却是30.02mil,正确的是20.…...

小白该从哪方面入手学习大数据

大数据本质上是海量数据。 以往的数据开发&#xff0c;需要一定的Java基础和工作经验&#xff0c;门槛高&#xff0c;入门难。 如果零基础入门数据开发行业的小伙伴&#xff0c;可以从Python语言入手。 Python语言简单易懂&#xff0c;适合零基础入门&#xff0c;在编程语言…...

尚医通(十)数据字典加Redis缓存 | MongoDB

目录一、Redis介绍二、数据字典模块添加Redis缓存1、service_cmn模块&#xff0c;添加redis依赖2、service_cmn模块&#xff0c;添加Redis配置类3、在service_cmn模块&#xff0c;配置文件添加redis配置4、通过注解添加redis缓存5、查询数据字典列表添加Redis缓存6、bug&#x…...

为什么我们不再发明编程语言了?

上个世纪&#xff0c;数百种编程语言被发明出来&#xff0c;但是进入21世纪&#xff0c;当我们都进入互联网时代时&#xff0c;只剩那么寥寥几个了。 如果你翻一下TIOBE得编程语言排行榜&#xff0c;就会发现20年来&#xff0c;上蹿下跳的就是那几张老面孔&#xff1a;C , Java…...

预处理指令详解

预处理指令详解**1.预定义符号****2.#define****2.1 #define 定义标识符****2.2 #define 定义宏****2.3 #define 替换规则****2.4 #和##****#的作用****##的作用****2.5 带副作用的宏参数****2.6 宏和函数的对比****宏和函数对比图****2.7 命名约定****3.#undef**4.条件编译4.1…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

pycharm 设置环境出错

pycharm 设置环境出错 pycharm 新建项目&#xff0c;设置虚拟环境&#xff0c;出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

02.运算符

目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&&#xff1a;逻辑与 ||&#xff1a;逻辑或 &#xff01;&#xff1a;逻辑非 短路求值 位运算符 按位与&&#xff1a; 按位或 | 按位取反~ …...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...

麒麟系统使用-进行.NET开发

文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的&#xff0c;如果需要进行.NET开发&#xff0c;则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET&#xff0c;所以要进…...