【力扣高频题】004.两个正序数组的中位数

------------------ 长文警告 ------------------

4.两个正序数组的中位数

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数

算法的时间复杂度应该为 O ( l o g ( m + n ) ) O(log(m+n)) O(log(m+n))

示例 1:

输入: nums1 = [1,3], nums2 = [2]

输出: 2.00000

解释: 合并数组 = [1,2,3] ,中位数 2 。

示例 2:

输入: nums1 = [1,2], nums2 = [3,4]

输出: 2.50000

解释: 合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5 。

思路分析

本题的暴力思路其实很简单:

  • 由于两个数组是正序的,因此可以采用 双指针 的方式将两个数组合并成为一个新的有序数组,并根据m + n为奇数还是偶数返回其中位数即可
  • 该方法由于使用了双指针的方式,需要遍历整个数组,因此其时间复杂度为 O ( M a x ( m , n ) ) O(Max(m,n)) O(Max(m,n))

但由于本题要求时间复杂度为 O ( l o g ( m + n ) ) O(log(m+n)) O(log(m+n)),因此需要探究一种更加高效的算法。


接下来我们先来介绍并实现 两个函数 ,进而对本题进行求解。

函数一:

函数功能: 合并两个有序且长度相等的数组,返回其中位数(奇数长度时)或上中位数(偶数长度时)。因此很显然,需要分两种情况进行讨论。

  • 长度为偶数
    • 以数组长度为 4 进行举例说明:


  • 长度为奇数
    • 以数组长度为 5 进行举例说明:

因此,为了能够继续使用该函数进行递归,需要从较长数组中舍弃一个。

舍弃方法是:长数组的最小值与短数组的最大值进行比较 。

函数二:

函数功能: 合并两个有序但不一定等长的数组,返回其第 K 小的数。

下面对以上三种不同的情况进行讨论分析,为方便说明,取n = 3m = 7



与情况 2)推广与证明方法类似,这里不再赘述,感兴趣的小伙伴可以仿照 2)证明一下该方法的正确性。


至此,我们就介绍完了两个函数的功能:

函数一getUpMedian 合并两个有序且长度相等的数组,返回其上中位数。

函数二findKthNum 合并两个有序但不一定等长的数组,返回其第 K 小的数。

实现了这两个函数功能后,本题主函数思路就很容易构思到了:

给定两个任意长度的数组后,

  1. 若两数组长度之和为奇数时,调用findKthNum(size/2+1),求中位数。
  2. 若两数组长度之和为偶数时,调用findKthNum(size/2)findKthNum(size/2+1),再求二者均值,即中位数。
  3. 注意考虑边界条件,若其中一个数组长度为 0 ,直接返回另外一个有序数组的上中位数即可。

函数一代码

public static int getUpMedian(int[] A, int s1, int e1, int[] B, int s2, int e2) {int mid1 = 0;int mid2 = 0;while (s1 < e1) {mid1 = (s1 + e1) / 2;mid2 = (s2 + e2) / 2;if (A[mid1] == B[mid2]) {return A[mid1];}if (((e1 - s1 + 1) & 1) == 1) { // 奇数长度if (A[mid1] > B[mid2]) {if (B[mid2] >= A[mid1 - 1]) {return B[mid2];}e1 = mid1 - 1;s2 = mid2 + 1;} else { // A[mid1] < B[mid2]if (A[mid1] >= B[mid2 - 1]) {return A[mid1];}e2 = mid2 - 1;s1 = mid1 + 1;}} else { // 偶数长度if (A[mid1] > B[mid2]) {e1 = mid1;s2 = mid2 + 1;} else {e2 = mid2;s1 = mid1 + 1;}}}return Math.min(A[s1], B[s2]);
}

函数二代码

public static int findKthNum(int[] arr1, int[] arr2, int K) {int[] longs = arr1.length >= arr2.length ? arr1 : arr2;int[] shorts = arr1.length < arr2.length ? arr1 : arr2;int m = longs.length;int n = shorts.length;if (K <= n) {return getUpMedian(shorts, 0, K - 1, longs, 0, K - 1);}if (K > m) {if (shorts[K - m - 1] >= longs[m - 1]) {return shorts[K - m - 1];}if (longs[K - n - 1] >= shorts[n - 1]) {return longs[K - n - 1];}return getUpMedian(shorts, K - m, n - 1, longs, K - n, m - 1);}if (longs[K - n - 1] >= shorts[n - 1]) {return longs[K - n - 1];}return getUpMedian(shorts, 0, n - 1, longs, K - n, K - 1);
}

主函数

public static double findMedianSortedArrays(int[] nums1, int[] nums2) {int n1 = nums1.length;int n2 = nums2.length;int size = n1 + n2;boolean even = (size & 1) == 0;if (n1 != 0 && n2 != 0) {if (even) {return (double) (findKthNum(nums1, nums2, size / 2) + findKthNum(nums1, nums2, size / 2 + 1)) / 2D;} else {return findKthNum(nums1, nums2, size / 2 + 1);}} else if (n1 != 0) {if (even) {return (double) (nums1[(size - 1) / 2] + nums1[size / 2]) / 2;} else {return nums1[size / 2];}} else if (n2 != 0) {if (even) {return (double) (nums2[(size - 1) / 2] + nums2[size / 2]) / 2;} else {return nums2[size / 2];}} else {return 0;}
}

复杂度分析

findKthNum函数和getUpMedian函数,由于采用了递归调用求解第 K 小的数字或上中位数,每次递归根据不同位置,几乎抛弃了一半的一定不可能出现的数组元素。

因此,时间复杂度为 O ( l o g ( m + n ) ) O(log(m+n)) O(log(m+n))

总结

本题的思维量较大,能够认真阅读完的小伙伴很不容易啦 ~

在解决该题的 中位数问题 时,我们顺便解决了如何寻找两个有序但不一定等长的数组中 第 K 小的数 的方法,该方法适用的 范围更广泛 ,能够适当迁移去解决其他问题哦!!!

写在最后

前面的算法文章,更新了许多 专题系列 。包括:滑动窗口、动态规划、加强堆、二叉树递归套路 等。

还没读过的小伙伴可以关注,在主页中点击对应链接查看哦~

接下来的一段时间,将持续 「力扣高频题」 系列文章,想刷 力扣高频题 的小伙伴也可以关注一波哦 ~

~ 点赞 ~ 关注 ~ 星标 ~ 不迷路 ~!!!

回复「ACM紫书」获取 ACM 算法书籍 ~
回复「算法导论」获取 算法导论第3版 ~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/36336.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工业数据分析要用FusionInsight MRS IoTDB ?

随着工业互联网逐步兴起&#xff0c;在加速工业自动化、智能化的同时&#xff0c;也进一步加速工业生产时间序列数据的产生速度。但对于工业生产中的数据分析&#xff0c;仍然存在重复样本多&#xff0c;数据膨胀率大&#xff0c;缺乏专业易用的平台&#xff0c;这些问题成为阻…

NFS文件共享服务搭建

文章目录 NFS介绍特点用途 NFS版本NFS安装0. 安装规划1. 安装NFS服务2. 启动并启用服务3. 创建共享目录4. 配置NFS共享5. 应用NFS配置6. 防火墙设置7. 验证NFS服务8. 客户端挂载9. 验证挂载10. 客户端卸载nfs挂载11. 自动挂载 参考文章 NFS介绍 NFS&#xff08;Network File Sy…

linux的常用系统维护命令

1.ps显示某个时间点的程序运行情况 -a &#xff1a;显示所有用户的进程 -u &#xff1a;显示用户名和启动时间 -x &#xff1a;显示 没有控制终端的进程 -e &#xff1a;显示所有进程&#xff0c;包括没有控制终端的进程 -l &#xff1a;长格式显示 -w &#xff1a;宽…

k8s部署mongodb副本高可用集群

此版本的NFS为单点,仅为练习使用,生产环境建议使用cephfs的卷类型,避免单点。或者通过keepalived加Sersync的方案对NFS作容灾处理即可用于生产环境。当然,对于开发或测试环境,方便起见,直接使用单点的NFS加mongodb statefulSet方案是最为清晰简便的。 mongodb集群部署分…

Gemma 2大模型:性能更优,效率更高

当地时间6月27日&#xff0c;谷歌正式发布了在一个月前的I/O开发者大会上预告过的Gemma 2大模型。这款新模型相较于第一代Gemma模型&#xff0c;在性能和推理效率上都有了显著的提升&#xff0c;为AI领域带来了新的突破。 据谷歌介绍&#xff0c;Gemma 2模型包括9B和27B两种参…

创建github个人博客

文章目录 安装Hexo安装git安装Node.js安装 Hexo git配置SSH key配置ssh 搭建个人博客新建博客生成静态网页 本文主要参考 【保姆级】利用Github搭建自己的个人博客&#xff0c;看完就会 安装Hexo 参考官方文档&#xff1a;https://hexo.io/zh-cn/docs/ Hexo 是一个快速、简洁且…

微服务实战系列之云原生

前言 话说博主的微服务实战系列从去年走到今天&#xff0c;已过去了半年多了。本系列&#xff0c;博主主要围绕微服务实践过程中的主要组件或工具展开介绍。其中基本覆盖了我们项目或产品研发过程中&#xff0c;经常使用的中间件或第三方工具。至此&#xff0c;该系列也该朝着…

2024年河北省计划招聘“特岗计划”教师2300名

2024年河北省计划招聘“特岗计划”教师2300名 报名时间&#xff1a;6月28日9:00至7月2日18:00 笔试准考证打印&#xff1a;7月11日-7月13日 笔试时间&#xff1a;7月14日上午9:00-11:30 面试时间&#xff1a;8月3日至8月5日 报名网站&#xff1a;河北教师教育网 报名照规格&…

2024全新【大模型学习路径导航】从入门到精通的全面规划

引言 随着人工智能技术的迅猛发展&#xff0c;大模型成为了引领技术变革的关键力量。无论你是对大模型领域感兴趣的初学者&#xff0c;还是希望深化理解并应用大模型的开发者&#xff0c;这份精心策划的学习路径将为你提供从零基础到精通的全面指导。 第一阶段&#xff1a;基…

Pytest--安装与入门

pytest是一个能够简化成测试系统构建、方便测试规模扩展的框架&#xff0c;它让测试变得更具表现力和可读性–模版代码不再是必需的。只需要几分钟的时间&#xff0c;就可以对你的应用开始一个简单的单元测试或者复杂的功能测试。 1. 安装pytest pip install -U pytest检查版…

基于Java影院管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f;感兴趣的可以先收藏起来&#xff0c;还…

树莓派4B学习笔记14:Python多线程编程_线程间的同步通信_(锁‘threading.Lock’)

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 今日学习树莓派与Python的多进程编程_线程间同步通信 文…

axios之CancelToken取消请求

从 v0.22.0 开始&#xff0c;Axios 支持以 fetch API 方式—— AbortController 取消请求 此 API 从 v0.22.0 开始已被弃用&#xff0c;不应在新项目中使用 官网链接 1. 背景 最近项目中遇到一个场景&#xff0c;当连续触发一个请求时&#xff0c;如果是同一个接口&#xf…

【Redis-04 补充】Redis事务

【Redis-04 补充】Redis事务 1. 事务冲突的问题1.1 举例1.2 悲观锁1.3 乐观锁1.4 Redis中的乐观锁 WATCH key [key …]1.5 Redis事务三特性 2. 秒杀案例2.1 相关代码2.2 模拟并发工具httpd-tools 3. 设计一个秒杀系统3.1 预热库存3.2 秒杀请求3.3 生成订单3.4 限流与防刷 4. 总…

【代码随想录】【算法训练营】【第52天】 [647]回文子串 [516]最长回文子序列

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 52&#xff0c;周五&#xff0c;开始补作业了~ 题目详情 [647] 回文子串 题目描述 647 回文子串 解题思路 前提&#xff1a;寻找回文子串&#xff0c;子串意味着元素连续 思路&#xff1a;…

Android 10.0 关于定制自适应AdaptiveIconDrawable类型的动态时钟图标的功能实现系列一

1.前言 在10.0的系统rom定制化开发中,在关于定制动态时钟图标中,原系统是不支持动态时钟图标的功能,所以就需要从新 定制动态时钟图标关于自适应AdaptiveIconDrawable类型的样式,就是可以支持当改变系统图标样式变化时,动态时钟 图标的背景图形也跟着改变,所以接下来就来…

低代码+定制:优化项目管理的新方案

引言 在当今快速变化的商业环境中&#xff0c;企业需要更加灵活、高效的项目管理工具。低代码平台作为一种新的开发方式&#xff0c;因其能够快速构建应用程序而受到广泛关注。与此同时&#xff0c;软件定制开发仍然是满足特定复杂需求的重要手段。在项目管理中&#xff0c;低代…

【RT摩拳擦掌】基于RT106L/S语音识别的百度云控制系统

【RT摩拳擦掌】基于RT106L/S语音识别的百度云控制系统 一 文档简介二 平台构建2.1 使用平台2.2 百度智能云2.2.1 物联网核心套件2.2.2 在线语音合成 2.3 playback语音数据准备与烧录2.4 开机语音准备与添加2.5 唤醒词识别词命令准备与添加 三 代码准备3.1 sln-local/2-iot 代码…

【开发环境】MacBook M2安装git并拉取gitlab项目,解决gitlab出现Access Token使用无效的方法

文章目录 安装Homebrew安装git打开IDEA配置git打开IDEA拉取项目 安装Homebrew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"在iTerm等命令行工具打开后&#xff0c;输入上面的命令 之后根据中文提示完成Homebrew的下载…