【力扣高频题】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;这些问题成为阻…

【PYTHON】力扣刷题笔记 -- 0053. 最大子数组和【中等】

题目描述&#xff1a;给你一个整数数组 array: nums &#xff0c;请你找出一个具有最大和的连续子数组 sub-array&#xff0c;返回其最大和 子数组&#xff08;最少包含一个元素&#xff09;: 是数组中的一个连续部分 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1…

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…

golang 如何判断当前是否是运行单元测试?

我们在go的模块化开发的时候&#xff0c;运行模块里面的单元测试时&#xff0c;当前整个模块的 init 函数都会被执行&#xff0c;在某些情况下我们运行独立的单元测试并不需要执行其他文件里面的init函数&#xff0c;这时就需要判断当前是否是在运行单元测试&#xff0c;判断方…

linux的常用系统维护命令

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

jEasyUI 自定义排序

jEasyUI 自定义排序 jEasyUI 是一个基于 jQuery 的框架,用于创建富交互的网页界面。它提供了一系列的组件,如布局、窗口、数据网格等,使得用户能够轻松地构建功能强大的用户界面。在数据网格(datagrid)组件中,排序功能是一个非常重要的特性,它允许用户根据列的值对数据…

k8s部署mongodb副本高可用集群

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

66.前端接口调用返回400的错误

错误代码400通常表示由于无效的请求导致服务器无法处理请求。这可能是由于以下原因之一&#xff1a; 1.语法错误&#xff1a;客户端发送的请求可能存在语法错误&#xff0c;例如缺少必需的参数、格式不正确等。 2.未授权&#xff1a;如果API需要认证&#xff0c;而客户端没有提…

代谢组数据分析十一:典型相关分析

欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2介绍 典型相关分析(Canonical Correlation Analysis,简称CCA)是一种统计方法,用于探索两组变量之间的线性关系。与主成分分析(PCA)不同,PCA是在同一…

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 是一个快速、简洁且…

探索WebKit的守护神:深入Web安全策略

探索WebKit的守护神&#xff1a;深入Web安全策略 在数字化时代&#xff0c;网络已成为我们生活的一部分&#xff0c;而网页浏览器作为我们探索网络世界的窗口&#xff0c;其安全性至关重要。WebKit作为众多流行浏览器的内核&#xff0c;例如Safari&#xff0c;其安全性策略是保…

【其他】这阵子虚拟机编译和重启次数太多后果

1、开始蓝屏的次数没有&#xff0c;随着VM的Ubuntu每天大量的编译&#xff0c;代码里边各种加while(1)&#xff0c;估计是加重了宿主机的负担吧&#xff0c;宿主机后来&#xff08;大概是十天前&#xff09;是一天蓝屏1次&#xff1b;慢慢增加现在是一天大概蓝屏6次&#xff0c…

微服务实战系列之云原生

前言 话说博主的微服务实战系列从去年走到今天&#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;河北教师教育网 报名照规格&…

Spring Boot中使用Actuator监控应用状态

Spring Boot中使用Actuator监控应用状态 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨如何在Spring Boot应用中使用Actuator来监控和管理应…

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

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

[机器学习]-1 概要介绍

1 理论来源 机器学习理论是参照人类学习链条&#xff1a;DIKIW模型&#xff08;数据-信息-知识-智能-智慧&#xff09; -数据: 原始的、未经处理的事实和数字。 -信息: 经过处理、整理和结构化的数据&#xff0c;具有意义和上下文。 -知识: 由信息构建而成的模式和规则。 -智能…

Pytest--安装与入门

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