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

数组-两个升序数组中位数

一、题目描述

二、解题思路

(一).基本思想:

如果列表总长度allsize( =arr1.size()+arr2.size() ) 为奇数时,中位数位置应该在两个列表排序后的第 allsize/2 位置处,如果allsize为偶数,中位数应该取 (allsize/2)-1 和 allsize/2 的平均数。

设置两个指针p1、p2,一个指向列表 arr1[0] ,一个指向列表 arr2[0] ,比较两个指针指向列表的值,值较小的指针往后移动一位

再次比较p1、p2,重复上述动作。

(二).注意:因为两个列表长度不一定相同,所以存在某一个指针p1遍历到列表末尾,但是仍然没有找到中位数,这时候中位数有可能就会出现①p1、p2均在列表中间,此时取二者较小值或者平均值、②在另一个列表中、③另一个列表中两个元素取平均值、④p1(此时在末尾)和p2取平均值、⑤p1(此时在末尾)这几种情况,下面就对各种可能出现的情况进行举例说明,以写出比较严谨的代码实现,覆盖各种可能出现的情况。

比较次数和总列表长度的奇偶性还有确定中位数位置是有关联性的,这一点可以自己在下面例子里尝试一下。

1.当allsize为奇数时:只存在一个中位数,此时比较次数为 allsize/2 次

(1).p1、p2在中间位置

        [1,2,3,8,9] 和 [4,5,6,7] ,总列表 [1,2,3,4,5,6,7,8,9]

        总长度为9,比较4次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->2,p2->4,p1<p2,p1++;

                第三次 p1->3,p2->4,p1<p2,p1++;

                第四次 p1->8,p2->4,p1>p2,p2++;

                此时:p1->8,p2->5 取二者较小值为5,中位数为5

(2).p1在arr1末尾,并且p1<=p2时

        [1,2,3,4]和[5,6,7,8,9],总列表 [1,2,3,4,5,6,7,8,9]

        总长度为9,比较4次:

                第一次 p1->1,p2->5,p1<p2,p1++;

                第二次 p1->2,p2->5,p1<p2,p1++;

                第三次 p1->3,p2->5,p1<p2,p1++;

                第四次 p1->4,p2->5,p1<p2,此时p1已经在末尾,不再++,设置变量标记中位数在arr2中(p2侧);

                此时:直接取p2为中位数,中位数为5

(3).p1在arr1末尾,并且p1>p2时

        [1,2,3,5]和[4,6,7,8,9],总列表 [1,2,3,4,5,6,7,8,9]

        总长度为9,比较4次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->2,p2->4,p1<p2,p1++;

                第三次 p1->3,p2->4,p1<p2,p1++;

                第四次 p1->5,p2->4,p1>p2,此时p2++;

                此时:p1->5,p2->6 取p1、p2二者较小值,中位数为5

2.当allsize为偶数时,中位数等于中间两个元素取平均值,此时两个元素比较次数为 allsize/2 -1 次,执行完allsize/2 -1 次判断时: 

(1).p1、p2在中间位置,并不能确定中间两个数在哪一侧产生,可能是两侧各贡献一个(包括p1或者p2没有发生移动的情况)

        两侧各贡献一个:

        (这种情况牛客里面的测试用例没有覆盖这种情况,刚开始我写的代码这部分有缺陷,所以会出现问题,下面的代码实现已经补上了处理策略,判断过程看下面加粗黄色说明部分)

        [1,2,3,8,9] 和 [4,5,6,7,10] ,总列表 [1,2,3,4,5,6,7,8,9,10]

        总长度为10,比较4次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->2,p2->4,p1<p2,p1++;

                第三次 p1->3,p2->4,p1<p2,p1++;

                第四次 p1->8,p2->4,p1>p2,p2++;

                此时:p1->8,p2->5,最后一次移动的是p2(作为求平均数的左值),且p2未到达末尾,需要比较(p2+1)和p1位置的值,(p2+1)->6,p1->8,取二者较小值为6,中位数为(5+6)/2=5.5

        

        [4,5,6,7,10] 和 [1,2,3,8,9] ,总列表 [1,2,3,4,5,6,7,8,9,10]

        总长度为10,比较4次:

                第一次 p2->4,p1->1,p1>p2,p2++;

                第二次 p1->4,p2->2,p1>p2,p2++;

                第三次 p1->4,p2->3,p1>p2,p2++;

                第四次 p1->4,p2->8,p1<p2,p1++;

                此时:p1->5,p2->8,最后一次移动的是p1(作为求平均数的左值),且p1未到达末尾,需要比较(p1+1)和p2位置的值,(p1+1)->6,p1->8,取二者较小值为6,中位数为(5+6)/2=5.5


        p1或者p2没有发生移动的情况:

        [1,2,3,7]和[4,5,8,9],总列表 [1,2,3,4,5,7,8,9]

        总长度为8,比较3次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->2,p2->4,p1<p2,p1++;

                第三次 p1->3,p2->4,p1<p2,p1++;

                此时:p1->7,p2->4  需要比较一下p1和p2+1位置的大小,如果p1>p2+1,中位数选择p2和p2+1位置元素和的平均值;如果p1<p2+1,中位数选择p1和p2的平均值。

                

        [4,5,8,9] 和 [1,2,3,7],总列表 [1,2,3,4,5,7,8,9]

        总长度为8,比较3次:

                第一次 p1->4,p2->1,p1>p2,p2++;

                第二次 p1->4,p2->2,p1>p2,p2++;

                第三次 p1->4,p2->3,p1>p2,p2++;

                此时:p1->4,p2->7 需要比较一下p2和p1+1位置的大小,如果p2>p1+1,中位数选择p1和p1+1位置元素和的平均值;如果p2<p1+1,中位数选择p1和p2的平均值。


        并不能确定是否只出现在一侧的情况:

        [1,8] 和 [4,5,6,7,8,9],总列表 [1,4,5,6,7,8,8,9]

        总长度为8,比较3次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->8到达末尾,p2->4,p1>p2,p2++;

                第三次 p1->8到达末尾,p2->5,p1>p2,p2++;

                此时:p1->8,p2->6  p1到达末尾,p2一定是中间两个数之一,需要比较一下p2+1和p1的大小,取较小值作为另一个数,p2+1->7,p1->8,取p2+1和p2的平均数作为中位数,值为6.5。

(2).p1早已到达arr1末尾,确定两个数确定在p2侧产生

         [6,7] 和 [5,9,10,11,12,13],总列表 [5,6,7,9,10,11,12,13]

        总长度为8,比较3次:

                第一次 p1->6,p2->5,p1>p2,p2++;

                第二次 p1->6,p2->9,p1<p2,p1++;

                第三次 p1->7到达末尾,p2->9,p1<p2,p2++,且设置标志位;

                此时:中间两个数只会是p2和p2+1位置的值,计算两个数的平均数:p2->9,(p2+1)->10,平均值为8.5。

(3).p2早已到达arr2末尾,中间两个数确定在p1侧产生,这个执行过程大家自己根据上面(2)的过程推理一下。

       [5,9,10,11,12,13] 和 [6,7],总列表 [5,6,7,9,10,11,12,13]

三、代码实现

import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param nums1 int整型ArrayList* @param nums2 int整型ArrayList* @return double浮点型*/public double Median (ArrayList<Integer> nums1, ArrayList<Integer> nums2) {double res = 0;int allsize = nums1.size() + nums2.size();int mididx = allsize / 2;int icounter=0;boolean oddnum=false;//奇数数if(allsize%2!=0){oddnum=true;//此时根据side判断取哪一侧的值,如果没有出现倾斜情况,则取p1、p2较小值icounter=mididx;}else{oddnum=false;//此时取p1和p2位置平均值icounter=mididx-1;}int p1 = 0, p2 = 0;boolean p1side=false,p2side=false;int lastestmove=0;while (icounter > 0) {if (p1 < (nums1.size() - 1) && nums1.get(p1) <= nums2.get(p2)) {p1++;lastestmove=1;}else if(p1 == (nums1.size() - 1)){if(!oddnum){if(!p2side&&nums1.get(p1)>nums2.get(p2)){p2++;lastestmove=2;}else if(!p2side&&nums1.get(p1)<=nums2.get(p2)){p2side=true;}else{p2++;lastestmove=2;}    }else{if(!p2side&&nums1.get(p1)>nums2.get(p2)){p2++;lastestmove=2;}else{if(!p2side){p2side=true;}else{p2++;lastestmove=2;}}}}else if (p2 < (nums2.size() - 1) && nums1.get(p1) > nums2.get(p2)) {p2++;lastestmove=2;}else if (p2 == (nums2.size() - 1)) {if(!oddnum){if(!p1side&&nums2.get(p2)>=nums1.get(p1)){p1++;lastestmove=1;}else if(!p1side&&nums2.get(p2)<nums1.get(p1)){p1side=true;}else{p1++;lastestmove=1;}    }else{if(!p1side&&nums2.get(p2)>nums1.get(p1)){p1++;lastestmove=1;}else{if(!p1side){p1side=true;}else{p1++;lastestmove=1;}}}}icounter--;}if (!oddnum) { //此时取中间两个值的平均数为中位数if(p1side){//中间两个数位于p1侧res=((double)(nums1.get(p1)) + (double)(nums1.get(p1+1))) / 2;}else if(p2side){//中间两个数位于p2侧res=((double)(nums2.get(p2)) + (double)(nums2.get(p2+1))) / 2;}else{double minright=(double)(nums2.get(p2));double minleft=(double)(nums1.get(p1));if(lastestmove==1){//此时p1为左值//偶数个数时,当最后一次移动发生在p1侧且p1侧没有到达末尾,比较p1+1和p2大小,取较小值作为右值minleft=(double)(nums1.get(p1));minright=nums1.get(p1+1)>nums2.get(p2)?nums2.get(p2):nums1.get(p1+1);}else if(lastestmove==2){//此时p2为右值//原理同上,比较p2+1和p1大小,取较小值minleft=(double)(nums2.get(p2));minright=nums2.get(p2+1)>nums1.get(p1)?nums1.get(p1):nums2.get(p2+1);}res=( minleft + minright) / 2;}} else { //此时取p1、p2两者较小的值if(p1side){res = nums1.get(p1);}else if(p2side){res = nums2.get(p2);}else{res = Math.min(nums2.get(p2),nums1.get(p1));}}return res;}
}

四、刷题链接

两个升序数组的中位数_牛客题霸_牛客网

五、近似题目

数组-在两个长度相等的有序数组中找到上中位数-CSDN博客文章浏览阅读272次,点赞4次,收藏6次。java刷题:查找两个长度相等的有序数组中的上中位数。https://blog.csdn.net/hehe_soft_engineer/article/details/139200124?spm=1001.2014.3001.5502

相关文章:

数组-两个升序数组中位数

一、题目描述 二、解题思路 (一).基本思想&#xff1a; 如果列表总长度allsize( arr1.size()arr2.size() ) 为奇数时&#xff0c;中位数位置应该在两个列表排序后的第 allsize/2 位置处&#xff0c;如果allsize为偶数&#xff0c;中位数应该取 (allsize/2)-1 和 allsize/2 的…...

每日一题《leetcode--116.填充每个结点的下一个右侧结点》

https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/ 题目要求给每个结点的next指针进行填充&#xff0c;使每个结点的next指针指向其下一个右侧结点。如果右侧没有结点&#xff0c;则将next指针设置为空。 struct Node* connect(struct Node* root) {…...

【MySQL精通之路】InnoDB(6)-磁盘结构(5)-Redolog

主博客&#xff1a; 【MySQL精通之路】InnoDB(6)-磁盘上的InnoDB结构-CSDN博客 上一篇&#xff1a; 【MySQL精通之路】InnoDB-双写缓冲区-CSDN博客 下一篇: 目录 1.配置Redo Log容量&#xff08;MySQL 8.0.30或更高版本&#xff09; 2.配置重做日志容量&#xff08;MySQL…...

【探索自然语言处理:构建一个简单的文本分类器】

文章目录 前言文本预处理特征提取模型训练文本分类结论 前言 在信息时代&#xff0c;文本数据无处不在&#xff0c;从社交媒体帖子到客户反馈&#xff0c;文本是沟通和信息交流的主要媒介。自然语言处理&#xff08;NLP&#xff09;是人工智能的一个分支&#xff0c;它使计算机…...

概率论统计——大数定律

大数定律 弱大数定律&#xff08;辛钦大数定律&#xff09; 利用切比雪夫不等式&#xff0c;证明弱大数定律 应用 伯努利大数定理&#xff0c;&#xff08;辛钦大数定理的推论&#xff09; 证明伯努利大数定理 注意&#xff1a;这里将二项分布转化成0,1分布来表示&#xff0c;…...

vscode终端命令行前面出现两个conda环境名的问题决解方法

已经安装了conda&#xff0c;打开vscode的terminal时&#xff0c;命令行前面有两个虚拟环境名。 进入vscode的setting 找到Python->Python:Default Interpreter Path&#xff0c;把这个值复位&#xff0c;就可以解决。 如果不想前面带(base)&#xff0c;可以运行 conda co…...

“AI黏土人”一夜爆火,图像生成类应用应该如何长期留住用户?

文章目录 最近大火的“AI黏土人”&#xff0c;一股浓浓的《小羊肖恩》风。 凭借这这种搞怪的风格&#xff0c;“AI黏土人”等图像生成类应用凭借其创新技术和市场需求迅速崛起并获得巨大关注。然而&#xff0c;要保持用户黏性并确保长期发展&#xff0c;这些应用需要采取一系列…...

【MySQL精通之路】SQL优化(1)-查询优化(12)-块嵌套循环和批处理Key访问联接

在MySQL中&#xff0c;可以使用批处理Key访问&#xff08;BKA&#xff09;联接算法&#xff0c;该算法使用对联接表的索引访问和联接缓冲区。 BKA算法支持内联接、外联接和半联接操作&#xff0c;包括嵌套的外部联接。 BKA的优点包括由于更高效的表扫描而提高了联接性能。 此…...

SQL使用函数给多个分表添加同一字段

数据库中分表时&#xff0c;往往需要向多个分表中添加同一个字段&#xff0c;可以定义一个函数&#xff0c;每次调用这个函数向多个份表中添加同意字段。 1、创建函数示例&#xff1a; 在PostgreSQL中创建一个简单的函数 以下是一个在PostgreSQL中创建函数的简单示例&#x…...

OpenAI 再次刷新认知边界:GPT-4 颠覆语音助手市场,流畅度直逼真人互动?

前言 近日&#xff0c;美国人工智能研究公司 OpenAI 发布了其最新旗舰模型 GPT-4o&#xff0c;这一革命性的进展不仅标志着人工智能领域的新突破&#xff0c;更预示着即将步入一个全新的交互时代&#xff1f;GPT-4o 的发布&#xff0c;对于我们来说&#xff0c;意味着人工智能…...

UE5 使用外置摄像头进行拍照并保存到本地

连接外置摄像头功能&#xff1a;https://docs.unrealengine.com/4.27/zh-CN/WorkingWithMedia/IntegratingMedia/MediaFramework/HowTo/UsingWebCams/ 核心功能&#xff1a;UE4 相机拍照功能&#xff08;图片保存&#xff09;_ue 移动端保存图片-CSDN博客 思路是&#xff1a; …...

【C++】从零开始map与set的封装

送给大家一句话&#xff1a; 今日的事情&#xff0c;尽心、尽意、尽力去做了&#xff0c;无论成绩如何&#xff0c;都应该高高兴兴地上床恬睡。 – 三毛 《亲爱的三毛》 &#x1f303;&#x1f303;&#x1f303;&#x1f303;&#x1f303;&#x1f303;&#x1f303;&#x…...

Python可以声明并赋值一个hash类型变量吗?

在Python中&#xff0c;不能直接声明一个变量为hash类型&#xff0c;因为Python是一种动态类型语言&#xff0c;不需要&#xff08;也不能&#xff09;在声明变量时指定其类型。变量的类型是根据赋给它的值自动推断的。 将一个哈希值&#xff08;即一个整数&#xff09;赋值给…...

苗情灾情监控系统—提高农业生产效率

TH-MQ2苗情灾情监控系统是一种用于监测农作物生长状况和灾情的设备&#xff0c;通过实时监测和数据分析&#xff0c;帮助农民及时了解作物生长情况&#xff0c;采取相应的管理措施&#xff0c;提高农业生产效率和降低生产成本。 该系统通常由多种传感器、摄像头、数据传输模块等…...

wpf自定义按钮样式

在WPF中&#xff0c;自定义按钮样式可以通过创建一个ControlTemplate来实现。以下是一个简单的自定义按钮样式的例子&#xff1a; 首先&#xff0c;在你的WPF项目资源字典中定义按钮的ControlTemplate。 <Window.Resources><ControlTemplate x:Key"CustomButto…...

Meme币总市值突破630亿美元 以太坊ETF获批意味着代币化资产“完全安全”

近日&#xff0c;数字货币市场再次掀起轩然大波。一方面&#xff0c;Meme币总市值突破了630亿美元&#xff0c;令人瞠目结舌&#xff1b;另一方面&#xff0c;以太坊ETF的获批也引发了市场的广泛关注&#xff0c;被视为代币化资产的“完全安全”标志。 Meme币总市值飙升 Meme币…...

MySQL数据库语法(二)

一、数据库的创建 创建数据库CRATE DATABASE语法&#xff1a;CREATE DATABASE [IF NOT EXISTS]数据库名;功能&#xff1a;用给定的名字创建一个数据库如果数据库已经存在&#xff0c;发生一个错误。查看创建数据库&#xff1a;SHOW CREATE DATABASE <数据库名>&#xff…...

Linux makefile

Linux makefile 用makefile去自动编译和删除静态库和动态库 在实际开发中&#xff0c;项目的源代码文件比较多&#xff0c;按类型、功能、模块分别存放在不同的目录和文件中&#xff0c;哪些文件需要先编译&#xff0c;那些文件后编译&#xff0c;那些文件需要重新编译&#xf…...

信息安全基础知识

信息安全基础知识 安全策略表达模型是一种对安全需求与安全策略的抽象概念表达&#xff0c;一般分为自主访问控制模型&#xff08;HRU&#xff09;和强制访问控制模型&#xff08;BLP、Biba&#xff09;IDS基本原理是通过分析网络行为&#xff08;访问方式、访问量、与历史访问…...

【数据结构】链式二叉树(超详细)

文章目录 前言二叉树的链式结构二叉树的遍历方式二叉树的深度优先遍历前序遍历(先根遍历)中序遍历(中根遍历)后序遍历(后根遍历) 二叉树的广度优先遍历层序遍历 二叉树链式结构接口实现二叉树结点个数二叉树叶子结点个数二叉树的深度&#xff08;高度&#xff09;二叉树第k层结…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

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

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

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...