寻找两个有序数组的中位数

简介: 寻找两个有序数组的中位数

问题描述

给定两个大小为mn的有序数组nums1nums2,找出这两个有序数组的中位数。示例一:nums1=[1,3]nums2=[2]则中位数为2示例二:nums1=[12]nums2=[34]则中位数为(2+3/2=2.5示例三:nums1 = [1,3,6,8]nums2 = [2,4,7,9,10,15]输出结果为6.5


解决方案

当两个有序数组的长度之和为奇数的时候,中位数只有一个。当两个有序数组的长度之和为偶数的时候,则中位数为数组合并之后位于中间的两个数的平均数。这里我们使用二分查找求取中位数

上面第一排是长度为偶数的情况,用红色的分隔线隔开,此时中位数有两个,一个是2,一个是3分别是分割线左边最大数和分割线右边最小数。第二排是长度为奇数的情况下,同样用红色的分隔线隔开,我们用分隔线隔开时让左边多一个元素,则分隔线左边这个元素就是长度为奇数的有序数组的中位数。(相应的,如果让右边多一个元素,则分隔线右边这个元素就是中位数,两种方式都可以)同样的,在两个有序数组的情况下,我们也可以做一个划分,把两个有序数组划分成左边部分和右边部分,需要注意的是位于分割线左边的元素个数和位于分割线右边的元素个数应该大致相等。

1.如果两个有序数组的长度之和为偶数,则我们划分左边元素个数和右边元素个数是相等的。2.如果两个有序数组的长度之和为奇数,则我们划分左边元素个数比右边元素个数多一个。(同理:右边比左边多一个也是可以的)3.一个必须满足的条件:分隔线左边所有元素的数值<=分隔线右边所有元素数值。


因为两个都是有序数组,这样一来,中位数就一定只与分隔线两边黄色标记的数有关了。当两个有序数组的长度之和为奇数时,我们让左边多一个元素

这样一来,左边最大的那个值就是两个有序数组合并之后的中位数了。同样情况,当两个有序数组的长度之和为偶数时,我们划分两边元数个数相等,当然,左边所有元素数值<=右边所有元素数值。


如上图所示,黄色标记为合并之后数组的两个中位数,8就为左边元素最大值,而9为右边元素最小值假设数组1的长度为m,数组2的长度为nm+n为偶数时,则左边元素个数为(m+n)/2m+n为奇数时,我们认为左边的元素个数比右边元素个数多一个,则左边元素个数为(m+n+1)/2由于在编程语言中,除法是整数除法,而整数除法默认小数前的整数,所以当m+n为偶数时,让(m+n)/2 = (m+n+1)/2这样我们就可以把偶数和奇数两种写法合并起来,左边元素个数就都为(m+n+1)/2。这样我们就不用对数组长度之和的奇偶性进行讨论,只需要确定一个数组划分的位置,然后通过关系计算出另一个数组划分的位置。注意:在满足划分的情况下,还有一个条件就是在左边第一排的最大值要小于右边第二排的最小值,同样,左边第二排的最大值也要小于右边第一排的最小值,这样交叉成立,划分才成立。解决这个问题还存在几种特殊情况第一种情况:较短的数组在分隔线右边没有元素。


第二种情况:较短的数组在分隔线左边没有元素。
解决办法:首先判断第一个数组和第二数组长度,为了保证较短的数组为第一个数组使用条件语句进行判断:if(nums1.length>nums.length){int[] nums3 = nums1; nums1 = nums2; nums2 = nums3}这样就实现了一个数组和第二个数组位置交换,定义第一个数组分隔线右边第一个元素的下标为i同样,定义第二个数组分隔线右边的第一个元素的小标为j根据之前的分析,ij满足关系式:i+j=(m+n+1)/2,代表的是分隔线左边所有元素的个数。如果nums1数组较短,那么就应该在nums1[0m]左闭右闭区间里查找恰当的分隔线。分隔线所要满足的条件就是:前面所写的(注意定义left = 0Right = m分隔线左边所有元素需要满足的个数是:totalLeft= (m+n-1)/2i=left+(right-left)/2j = totalLeft – i利用循环的方法就能够找到分隔线的位置了。代码如下:Java寻找两个有序数组的中位数

package Solutions;

 

public class Solution {

 

    public double findMedianSortedArrays(){

 

        int[] nums1 = {1,3,6,8};

        int[] nums2 = {2,4,7,9,10,15};

 

        //为了使得分隔线在第二个数组的两侧都有元素,以至于不会出现访问时下标越界的情况

        if (nums1.length>nums2.length){

            //如果第一个数组长度大于第二个数组的长度

            //则将较短的那个数组设置成第一个数组

            int[] nums3 = nums1;

            nums1 = nums2;

            nums2 = nums3;

        }

        int m = nums1.length;

        int n = nums2.length;

 

        //分隔线左边的所有元素个数需要满足的个数 (m+n+1)/2

 

        int totalLeft = (m+n+1)/2;

 

        //nums1的区间[0m]里查找恰当的分割线,

        //使得nums1[i-1] <= nums2[j] &&nums[j-1] <= nums1[i]

 

        int left = 0;

        int right = m;

        while (left<right){

            int i = left+(right-left+1)/2;

            int j = totalLeft-i;

            if (nums1[i-1]>nums2[j]){

                //下一轮搜索的区间[left,i-1]

                right = i-1;

            }else {

                //下一轮搜索的区间是[i,right]

                left = i;

            }

        }

        int i = left;

        int j = totalLeft-i;

        int nums1LeftMax = i == 0? Integer.MIN_VALUE : nums1[i-1];

        int nums1RightMin = i == m? Integer.MAX_VALUE :nums1[i];

        int nums2LeftMax = j == 0? Integer.MIN_VALUE : nums2[j-1];

        int nums2RightMin = j == m? Integer.MAX_VALUE :nums2[j];

 

        if ((m+n)%2==1){

            return Math.max(nums1LeftMax,nums2LeftMax);

        }else {

            double a= (double) (Math.max(nums1LeftMax,nums2LeftMax)+Math.min(nums1RightMin,nums2RightMin))/2;

            System.out.println(a);

            return a;

        }

    }

    public static void main(String[] args) {

        Solution solution = new Solution();

        solution.findMedianSortedArrays( );

    }

}


结语

本文章简要介绍使用二分查找方法解决两个有序数组的中位数,解决这个问题还可以使用先将两个数组进行合并,然后再求取中位数。

目录
相关文章
|
1月前
|
安全 定位技术 API
个人用户必看!3 种准确查 IP 地址地理位置与运营商的实用方法
本文详解IP地理查询的原理与实操:解析IP“漂移”原因(动态分配、NAT、数据库滞后),对比在线网页、免费API、系统命令三种查询方式,并提供准确率提示与实用小贴士,助力用户快速定位IP归属地与运营商。
2094 1
|
3月前
|
人工智能 安全 搜索推荐
2026 AI 元年:智能时代的正式启幕
当 2026 年的时钟敲响,人工智能领域迎来历史性转折点 —— 从技术迭代的 “积累期” 正式迈入产业落地的 “爆发期”,2026 年也因此被定义为真正意义上的 “AI 元年”,标志着智能时代的正式启幕。这一年,大模型技术完成从 “能力突破” 到 “价值兑现” 的关键跨越,智能体成为企业数字化转型的核心载体,AI 普惠化浪潮席卷各行各业,技术、产业、政策的三重协同让 AI 真正从实验室走向产业一线、从概念走向实用。本文立足 2026 年这一关键时间节点,深度剖析 AI 元年到来的核心驱动因素,全景解读智能时代启幕下的制造业、金融业、服务业等全产业变革图景,预判 2026 年后 AI 协同化、
1238 1
|
机器学习/深度学习 数据采集 人工智能
【技术揭秘】高性能粤语语音识别模型构建方案
随着人工智能技术的飞速发展,语音识别(Automatic SpeechRecognition)的应用越来越广泛,对于多语种多口音语音识别的需求也在日渐增加。虽然语音识别系统的基本原理和框架是不受限于语种的,在建立一个新语种的ASR模型时,还是需要结合到语言本身的特点,才能得到较好的效果。
【技术揭秘】高性能粤语语音识别模型构建方案
|
5月前
|
人工智能 缓存 语音技术
基于Rokid CXR-M SDK实现AR智能助手应用:让AI大模型走进AR眼镜
本文记录使用Rokid CXR-M SDK开发AR AI助手的全过程,涵盖SDK集成、语音识别、AI对接、结果推送等核心功能,分享实际开发中的技术选型、架构设计与踩坑经验,实现解放双手的实时语音问答体验。
744 6
基于Rokid CXR-M SDK实现AR智能助手应用:让AI大模型走进AR眼镜
|
5月前
|
人工智能 自然语言处理 供应链
低代码开发启蒙教程
低代码通过拖拽组件与可视化配置快速构建应用,支持数据编排、流程设计与多端发布,适用于OA系统、智能客服等场景,结合少量代码可扩展复杂功能,提升开发效率80%。
514 1
|
机器学习/深度学习 人工智能 自然语言处理
【AI大模型】ChatGPT模型原理介绍(下)
【AI大模型】ChatGPT模型原理介绍(下)
|
Ubuntu 网络协议 Linux
在Linux中,如何使用MTR进行网络诊断和路由跟踪?
在Linux中,如何使用MTR进行网络诊断和路由跟踪?
|
人工智能 Rust Apache
社区供稿 | 更长、更强、更开放,零一万物 Yi-1.5 系列开源模型发布一周广受好评
5 月 13 日,零一万物 Yi 系列开源模型全新升级为 Yi-1.5。相较于去年 11 月的开源版本,这次的 Yi-1.5 在保持原 Yi 系列模型优秀的通用语言能力的前提下,通过增量训练 500B 高质量 token,大幅提高了数学逻辑、代码能力。
|
SQL 关系型数据库 数据库
Python中SQLite数据库操作详解:利用sqlite3模块
【4月更文挑战第13天】在Python编程中,SQLite数据库是一个轻量级的关系型数据库管理系统,它包含在一个单一的文件内,不需要一个单独的服务器进程或操作系统级别的配置。由于其简单易用和高效性,SQLite经常作为应用程序的本地数据库解决方案。Python的内置sqlite3模块提供了与SQLite数据库交互的接口,使得在Python中操作SQLite数据库变得非常容易。
1951 5
|
JavaScript 关系型数据库 MySQL
❤Nodejs 第二章(Node连接本地数据库)
【4月更文挑战第2天】本文介绍了如何使用Node.js连接本地MySQL数据库。首先,提到了在MySQL官网下载安装数据库和使用Navicat for MySQL进行数据库管理。接着,通过`yarn add mysql`在项目中安装数据库依赖。然后,创建`app.js`文件,设置数据库连接参数,并建立连接进行查询操作。遇到导入模块的错误后,修改导入方式为CommonJS语法。
827 1

热门文章

最新文章

下一篇
开通oss服务