Leetcode:寻找两个正序数组的中位数

题目链接:4. 寻找两个正序数组的中位数 - 力扣(LeetCode)

题目分析

1、当只有一个有序数组时,该数组的中位数会将该数组分为两份:左子数组 和 右子数组

2、当有两个有序数组时, 我们仍然可以通过一条分隔线将两个数组分割,要求如下(前面两个是一个条件分开来写的,最后一个是一个条件,我们找到的分割线一共要满足两个条件)

  1. 两数组长度和为偶数时:分割线左右两侧元素个数相同
  2. 两数组长度和为奇数时:分割线左侧元素个数比右侧多一
  3. 分割线左侧的所有元素的数值 <= 分割线右侧所有元素的数值(交叉情况)
  • 不理解为什么要这样设置的,再想想中位数的定义,以及我们提供的数组是什么数组
  • 这样是为了确保中位数一定只与分割线两侧的元素有关,我们需要确定这条红线的位置

3、 假设两个有序数组的长度分别为m和n(这样计算可以保证分割线的第一个条件)

  • m+n为偶数时:分割线左侧元素个数为 = (m + n)/ 2 
  • m+n为奇数时:分割线左侧元素个数为 = (m + n + 1)/ 2 (因为我们之前规定中位线位于分割线左侧,所以分割线左侧元素个数要比右侧元素个数多一)
  • /是向下取整,故m+n为偶数时的计算式也可以变为(m + n + 1)/ 2,因此无论两个有序数组的长度和是奇数还是偶数,它们分割线左侧的元素个数均为(m + n + 1)/ 2

 4、只有一个有序数组时,分割线一定满足左侧所有元素 <= 右侧所有元素,但是在两个不同的有序数组的情况下不一定是这样的,我们需要对分割线进行适当调整(交叉情况)

  • 在代码中我们直接将最短的数组设置为第一个数组,因此不会存在第二个问题 

5、 由于我们需要访问分割线左右两侧的元素,因此如果某个数组过短或者两数组相等时,再去访问分割线两侧元素可能会导致越界访问的问题

  • 一个数组过短

  • 当两个数组长度相等时

补充:

1、分割线在第1个数组右边的第1个元素的下标i = 分割线在第1个数组左边的元素个数

2、分割线在第2个数组右边的第1个元素的下标j = 分割线在第2个数组左边的元素个数

普通版本(二分查找)

class Solution {
public:double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {if (nums1.size() > nums2.size())  //保证数组1一定最短{swap(nums1,nums2);}int m = nums1.size();int n = nums2.size();//两个数组分割线左侧所有的元素个数(分割线第一条件)int totalLeft = (m+n+1)/2;//在第一个数组[0,m]中寻找满足第二条件的分割线://第一个数组分割线左侧的数值 <= 第二个数组分割线右侧的数值 且 第二个数组分割线左侧的数值 <= 第一个数组分割线右侧的数值 //nums1[i - 1] <= nums2 [j] && nums2[j - 1] <= nums1[i](分割线第二条件)//提示1:分割线在第1个数组右边的第1个元素的下标i = 分割线在第1个数组左边的元素个数//提示2:分割线在第2个数组右边的第1个元素的下标j = 分割线在第2个数组左边的元素个数int left = 0;//第一个数组的左边界int right = m;//第一个数组的右边界//由于已提前将最短数组固定为nums1,所以在移动查找时候,i只会右移,j只会左移//循环查找while(left <right){int i = (left + right + 1)/ 2;//开始时先取一个中间位置的下标作为第一次的iint j = totalLeft - i;//第一个数组分割线左边的数有i个,两个数组分割线左侧的数有totalLeft个,totalLeft - i得到第二个数组分割线左侧的数的个数j//如果条件不满足就移动缩小判断范围(left右移或者right左移)if(nums1[i - 1] > nums2[j]) //如果第一个数组分割线左侧的数值大于第二个数组分割线右侧的数值,right左移一位,即分割线左移{right = i - 1;//下一轮的搜索区间为[left,i - 1]}else如果第一个数组分割线左侧的数值小于第二个数组分割线右侧的数值,left向右移动,即分割线右移{//下一轮的搜索区间为[i,right]left = i ;}}//循环结束表示已经在第一个数组中找到了合适的分割线int i = left;//i此时表示第一个数组中分割线右侧数值的下标int j = totalLeft - i;//j此时表示第二个数组中分割线右侧数值的下标int nums1LeftrMax = (i == 0 ? INT_MIN : nums1[i-1]);//两个数组长度相同时,第一个数组的分割线左侧的值不能被使用,第一个数组分割线左侧的数值设为整型最小值int nums1RightMin = (i == m ? INT_MAX : nums1[i]);//两个数组长度相同时,第一个数组的分割线右侧的值不能被使用,第一个数组分割线右侧的数值设为整型最大值int nums2LeftrMax = (j == 0 ? INT_MIN : nums2[j-1]);//两个数组长度相同时,第二个数组的分割线左侧的值不能被使用,第二个数组分割线左侧的数值设为整型最小值int nums2RightMin = (j == n ? INT_MAX : nums2[j]);//两个数组长度相同时,第二个数组的分割线左侧的值不能被使用,第二个数组分割线右侧的数值设为整型最大值//到这里,已经获取了两个数组分割线左右两侧的数值if((m+n) % 2 == 1) //两数组总长度为奇数时,获取的是两数组分割线左侧两个数的最大值{return max(nums1LeftrMax,nums2LeftrMax);}else//两数组总长度为偶数时,获取的是两数组分割线左侧两个数的最大值和分割线右侧两个数的最小值的平均值{return ((max(nums1LeftrMax,nums2LeftrMax) + min(nums1RightMin,nums2RightMin)) / 2.0);//整数 / 浮点数 = 浮点数,整数 / 整数 = 整数}}
};

问题1:int right = m; 为什么不是 m-1

        在二分查找中,right 的初始化为 m 而不是 m-1 是因为我们需要包括所有可能的分割线位置,包括数组的末尾。对于一个数组 numsm 是数组的长度,nums[m] 是有效的位置(\0)

  • 初始化 left = 0right = m 意味着我们在 [0, m] 范围内寻找分割线位置。
  • 如果初始化 right = m-1,则会遗漏数组的末尾分割位置,这是不正确的

问题2:/2.0/2 的区别

        在计算中位数时,为什么要使用 /2.0 而不是 /2,这是因为 2.0 是一个浮点数,使用浮点数除法可以确保结果是浮点数,而 /2 是整数除法,会丢失小数部分:

double result = (max(nums1LeftMax, nums2LeftMax) + min(nums1RightMin, nums2RightMin)) / 2.0;
  • /2.0 会进行浮点数除法,确保结果是 double 类型
  • /2 是整数除法,如果被除数是整数,则结果会是整数,丢失小数部分,导致计算不准确

 

~over~

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

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

相关文章

上岸极不保护一志愿院校经验。

这个系列会邀请上岸学长学姐进行经验分享~ 今天分享经验的同学上岸了哈尔滨工程大学。并不是对这所院校有什么歧视&#xff0c;只是按照往年择校数据来看&#xff0c;确实不太保护一志愿。大家自行斟酌&#xff0c;有利有弊。 经验分享 学长23年上岸哈尔滨工程大学水声工程学…

Sealos CLI快速部署部署K8s集群

1. Kubernetes基础环境部署 kubernetes有多种部署方式&#xff0c;目前主流的方式有kubeadm、minikube、二进制包 minikube&#xff1a;一个用于快速搭建单节点kubernetes的工具 kubeadm&#xff1a;一个用于快速搭建kubernetes集群的工具 二进制包 &#xff1a;从官网下载每…

社区供稿丨GPT-4o 对实时互动与 RTC 的影响

以下文章来源于共识粉碎机 &#xff0c;作者AI芋圆子 前面的话&#xff1a; GPT-4o 发布当周&#xff0c;我们的社区伙伴「共识粉碎机」就主办了一场主题为「GPT-4o 对实时互动与 RTC 的影响」讨论会。涉及的话题包括&#xff1a; GPT-4o 如何降低延迟&#xff08;VAD 模块可…

k8s集群搭建

k8s集群搭建 前期准备 1.关闭selinux 永久关闭selinux sed -i s/enforcing/disabled/g /etc/selinux/config更改后需重启系统 reboot2.关闭防火墙 systemctl stop firewalld && systemctl disable firewalld3.关闭swap内存分区 永久关闭swap分区 echo vm.swapp…

LabVIEW中进行步进电机的位置控制

在LabVIEW中进行步进电机的位置控制&#xff0c;通常涉及以下几个关键步骤&#xff1a;设置硬件、配置通信、编写控制算法和实施反馈控制。以下是一个详细的介绍。 硬件设置 步进电机&#xff1a;选择合适的步进电机&#xff0c;根据负载和应用需求选择适当的步数和转矩。 驱…

FL Studio21.2.8中文版让你的音乐创作如鱼得水

在音乐的世界里&#xff0c;我们都是探索者&#xff0c;追求着无尽的创新和可能性。而在这个过程中&#xff0c;我们往往会遇到各种挑战和困扰。如何快速高效地创作出满意的音乐作品&#xff1f;如何将我们的创意完美地呈现出来&#xff1f;这些问题可能一直困扰着你。今天&…

成都欣丰洪泰文化传媒有限公司助力品牌快速崛起

在当今数字化浪潮汹涌的时代&#xff0c;电商行业作为新经济的代表&#xff0c;正以其独特的魅力和无限的潜力&#xff0c;引领着商业模式的创新与变革。在这个充满机遇与挑战的领域里&#xff0c;成都欣丰洪泰文化传媒有限公司凭借其专业的电商服务能力和前瞻性的战略眼光&…

如何在.htaccess文件创建一个自定义404页面

本周有一个客户&#xff0c;购买Hostease的虚拟主机&#xff0c;询问我们的在线客服&#xff0c;如何在.htaccess文件创建一个自定义404页面&#xff1f;我们为用户提供相关教程&#xff0c;用户很快解决了遇到的问题。在此&#xff0c;我们分享这个操作教程&#xff0c;希望可…

NIFT和BMP批量互相转换(matlab)

前言&#xff1a;最近在做数据集&#xff0c;需要进行NIFT和BMP的批量互相转换。之前都是一张一张转换的&#xff0c;用Image J就能完成&#xff0c;但是最近数据太多了&#xff0c;所以得研究一下如何批量转换。 NIFT和BMP互相转换 NIFT和BMP介绍NIFTBMP 为什么要转换Matlab进…

MVC和MVVM

MVC Model层&#xff1a;用于处理应用程序数据逻辑的部分&#xff0c;通常负责在数据库中存取数据 View&#xff08;视图&#xff09;处理数据显示的部分。通常视图是依据模型数据创建的 Controller&#xff08;控制器&#xff09;是处理用户交互的部分。通常控制器负责从视…

从零开始学Vue3--环境搭建

1.搭建环境 下载nodejs nodejs下载地址 更新npm npm install -g npm 设置npm源&#xff0c;加快下载速度 npm config set registry https://registry.npmmirror.com 使用脚手架创建项目 npm create vuelatest 根据你的需要选择对应选项 进入新建的项目下载依赖 npm in…

Tasker+SendSilentMail实现钉钉自动打卡

Tasker 允许用户根据自定义的“配置文件”(Profiles)&#xff0c;在特定的“背景”(Contexts)下&#xff0c;执行指定的“任务”(Tasks)。以下是关于Tasker的详细介绍&#xff1a; 强大的自定义能力&#xff1a;用户可以根据自己的需求&#xff0c;创建各种配置文件和任务&…

【BUG】流式响应requests得到: ping - 和时间戳

前情提要 运行Langchain-Chatchat项目&#xff0c;使用自定义请求访问API Server流式输出 报错展示 b: ping - 2024-05-22 00:46:04.83252000:00\r\n\r\n报错原因 这通常是由于 Server-Sent Events (SSE) 实现中使用的“心跳”机制&#xff0c;以确保连接保持活跃。一些 SSE…

Java 在Word文档中添加、删除页面

在排版或者编辑Word文档时&#xff0c;可能会需要增加新页面或删除某个已有页面&#xff0c;以便更好地呈现内容。下面将介绍如何使用国产Java控件来实现在Word文档中增删页面的功能。 目录 Java 在Word文档末尾新增一页 Java 在Word文档指定位置插入一页 Java 删除Word文档…

百度ERNIE系列预训练语言模型浅析(4)-总结篇

总结&#xff1a;ERNIE 3.0与ERNIE 2.0比较 &#xff08;1&#xff09;相同点&#xff1a; 采用连续学习 采用了多个语义层级的预训练任务 &#xff08;2&#xff09;不同点&#xff1a; ERNIE 3.0 Transformer-XL Encoder(自回归自编码), ERNIE 2.0 Transformer Encode…

用Python实现办公自动化

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

用Kotlin协程消灭安卓开发中的回调地狱

原创 Pony 拍码场 安卓原生开发的痛点 自Android平台推出以来&#xff0c;Java一直是开发Android应用的主要语言。尽管后来Kotlin成为了谷歌主推的编程语言&#xff0c;Java仍然被广泛使用&#xff0c;在Android开发中仍占有重要地位。从github的数据看&#xff0c;用Java写的…

洗地机什么品牌质量好?家用洗地机排行榜

一年一度的大促节又到了&#xff0c;各大电商平台和实体店纷纷推出力度不小的折扣活动&#xff0c;吸引着消费者的关注和购买欲望。很多家庭也趁着这个机会&#xff0c;购置一些智能家居产品来提升生活品质。其中&#xff0c;洗地机作为近年来发展迅速的明星产品&#xff0c;受…

Redis篇 哈希表在redis中的命令

哈希命令 一.哈希表的基本认识二. 哈希表在redis中的命令1.hset,hget2.hdel3.hkeys,hvals4.hexists5.hgetall6.hmget7.hlen8.hincrby和hincrbyfloat 一.哈希表的基本认识 在JAVA数据结构中&#xff0c;我们就已经接触到了哈希表&#xff0c; 在当时&#xff0c;我们主要用到的哈…

人工智能和大模型的区别

人工智能&#xff08;AI&#xff09;和大模型是两个相关但有区别的概念。理解它们之间的区别有助于更好地掌握现代科技的发展动态。 人工智能&#xff08;AI&#xff09; 人工智能&#xff08;Artificial Intelligence, AI&#xff09;是一个广义的概念&#xff0c;指的是通过…