[Leedcode][JAVA][第4题][寻找两个正序数组中的中位数][二分查找][双指针]

【问题描述】[困难]

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。你可以假设 nums1 和 nums2 不会同时为空。示例 1:nums1 = [1, 3]
nums2 = [2]则中位数是 2.0
示例 2:nums1 = [1, 2]
nums2 = [3, 4]来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

【解答思路】

1. 数组合并

两个数组合并,两个有序数组的合并也是归并排序中的一部分。然后根据奇数,还是偶数,返回中位数
时间复杂度:O(N+M) 空间复杂度:O(1)

public double findMedianSortedArrays(int[] nums1, int[] nums2) {int[] nums;int m = nums1.length;int n = nums2.length;nums = new int[m + n];if (m == 0) {if (n % 2 == 0) {return (nums2[n / 2 - 1] + nums2[n / 2]) / 2.0;} else {return nums2[n / 2];}}if (n == 0) {if (m % 2 == 0) {return (nums1[m / 2 - 1] + nums1[m / 2]) / 2.0;} else {return nums1[m / 2];}}int count = 0;int i = 0, j = 0;while (count != (m + n)) {if (i == m) {while (j != n) {nums[count++] = nums2[j++];}break;}if (j == n) {while (i != m) {nums[count++] = nums1[i++];}break;}if (nums1[i] < nums2[j]) {nums[count++] = nums1[i++];} else {nums[count++] = nums2[j++];}}if (count % 2 == 0) {return (nums[count / 2 - 1] + nums[count / 2]) / 2.0;} else {return nums[count / 2];}
}
2. 双指针

在这里插入图片描述
时间复杂度:O(N+M) 空间复杂度:O(1)

public double findMedianSortedArrays(int[] A, int[] B) {int m = A.length;int n = B.length;int len = m + n;int left = -1, right = -1;int aStart = 0, bStart = 0;for (int i = 0; i <= len / 2; i++) {left = right;if (aStart < m && (bStart >= n || A[aStart] < B[bStart])) {right = A[aStart++];} else {right = B[bStart++];}}if ((len & 1) == 0)return (left + right) / 2.0;elsereturn right;
}
3. 求第 k 小数 k/2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
时间复杂度:O(log(m+n) 空间复杂度:O(1)

public double findMedianSortedArrays(int[] nums1, int[] nums2) {int n = nums1.length;int m = nums2.length;int left = (n + m + 1) / 2;int right = (n + m + 2) / 2;//将偶数和奇数的情况合并,如果是奇数,会求两次同样的 k 。return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5;  
}private int getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) {int len1 = end1 - start1 + 1;int len2 = end2 - start2 + 1;//让 len1 的长度小于 len2,这样就能保证如果有数组空了,一定是 len1 if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);if (len1 == 0) return nums2[start2 + k - 1];if (k == 1) return Math.min(nums1[start1], nums2[start2]);int i = start1 + Math.min(len1, k / 2) - 1;int j = start2 + Math.min(len2, k / 2) - 1;if (nums1[i] > nums2[j]) {return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));}else {return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));}}
4. 中位数

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
用完
在这里插入图片描述
长度相等
在这里插入图片描述
在这里插入图片描述
时间复杂度:O(N) 空间复杂度:O(1)

class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {int leftLength = nums1.length;int rightLength = nums2.length;// 为了保证第一个数组比第二个数组小(或者相等)if (leftLength > rightLength) {return findMedianSortedArrays(nums2, nums1);}// 分割线左边的所有元素需要满足的个数 m + (n - m + 1) / 2;// 两个数组长度之和为偶数时,当在长度之和上+1时,由于整除是向下取整,所以不会改变结果// 两个数组长度之和为奇数时,按照分割线的左边比右边多一个元素的要求,此时在长度之和上+1,就会被2整除,会在原来的数//的基础上+1,于是多出来的那个1就是左边比右边多出来的一个元素int totalLeft = (leftLength + rightLength + 1) / 2;// 在 nums1 的区间 [0, leftLength] 里查找恰当的分割线,// 使得 nums1[i - 1] <= nums2[j] && nums2[j - 1] <= nums1[i]int left = 0;int right = leftLength;// nums1[i - 1] <= nums2[j]//  此处要求第一个数组中分割线的左边的值 不大于(小于等于) 第二个数组中分割线的右边的值// nums2[j - 1] <= nums1[i]//  此处要求第二个数组中分割线的左边的值 不大于(小于等于) 第一个数组中分割线的右边的值// 循环条件结束的条件为指针重合,即分割线已找到while (left < right) {// 二分查找,此处为取第一个数组中左右指针下标的中位数,决定起始位置// 此处+1首先是为了不出现死循环,即left永远小于right的情况// left和right最小差距是1,此时下面的计算结果如果不加1会出现i一直=left的情况,而+1之后i才会=right// 于是在left=i的时候可以破坏循环条件,其次下标+1还会保证下标不会越界,因为+1之后向上取整,保证了// i不会取到0值,即i-1不会小于0// 此时i也代表着在一个数组中左边的元素的个数//+1 防止死循环int i = left + (right - left + 1) / 2;// 第一个数组中左边的元素个数确定后,用左边元素的总和-第一个数组中元素的总和=第二个元素中左边的元素的总和// 此时j就是第二个元素中左边的元素的个数int j = totalLeft - i;// 此处用了nums1[i - 1] <= nums2[j]的取反,当第一个数组中分割线的左边的值大于第二个数组中分割线的右边的值// 说明又指针应该左移,即-1if (nums1[i - 1] > nums2[j]) {// 下一轮搜索的区间 [left, i - 1]right = i - 1;// 此时说明条件满足,应当将左指针右移到i的位置,至于为什么是右移,请看i的定义} else {// 下一轮搜索的区间 [i, right]left = i;}}// 退出循环时left一定等于right,所以此时等于left和right都可以// 为什么left一定不会大于right?因为left=i。// 此时i代表分割线在第一个数组中所在的位置// nums1[i]为第一个数组中分割线右边的第一个值// nums[i-1]即第一个数组中分割线左边的第一个值int i = left;// 此时j代表分割线在第二个数组中的位置// nums2[j]为第一个数组中分割线右边的第一个值// nums2[j-1]即第一个数组中分割线左边的第一个值int j = totalLeft - i;// 当i=0时,说明第一个数组分割线左边没有值,为了不影响// nums1[i - 1] <= nums2[j] 和 Math.max(nums1LeftMax, nums2LeftMax)// 的判断,所以将它设置为int的最小值int nums1LeftMax = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];// 等i=第一个数组的长度时,说明第一个数组分割线右边没有值,为了不影响// nums2[j - 1] <= nums1[i] 和 Math.min(nums1RightMin, nums2RightMin)// 的判断,所以将它设置为int的最大值int nums1RightMin = i == leftLength ? Integer.MAX_VALUE : nums1[i];// 当j=0时,说明第二个数组分割线左边没有值,为了不影响// nums2[j - 1] <= nums1[i] 和 Math.max(nums1LeftMax, nums2LeftMax)// 的判断,所以将它设置为int的最小值int nums2LeftMax = j == 0 ? Integer.MIN_VALUE : nums2[j - 1];// 等j=第二个数组的长度时,说明第二个数组分割线右边没有值,为了不影响// nums1[i - 1] <= nums2[j] 和 Math.min(nums1RightMin, nums2RightMin)// 的判断,所以将它设置为int的最大值int nums2RightMin = j == rightLength ? Integer.MAX_VALUE : nums2[j];// 如果两个数组的长度之和为奇数,直接返回两个数组在分割线左边的最大值即可if (((leftLength + rightLength) % 2) == 1) {return Math.max(nums1LeftMax, nums2LeftMax);} else {// 如果两个数组的长度之和为偶数,返回的是两个数组在左边的最大值和两个数组在右边的最小值的和的二分之一// 此处不能被向下取整,所以要强制转换为double类型return (double) ((Math.max(nums1LeftMax, nums2LeftMax) + Math.min(nums1RightMin, nums2RightMin))) / 2;}}
}

【总结】

1. 二分查找法 log复杂度
2.边界复杂 多种情况 脑袋清晰
3.时间算法复杂度可以让简单题变复杂题

转载链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/
参考视频与评论:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-s-114/

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

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

相关文章

html:(5):了解html的代码注释和语义化

了解HTML的代码注释 什么是代码注释&#xff1f;代码注释的作用是帮助程序员标注代码的用途&#xff0c;过一段时间后再看你所编写的代码&#xff0c;就能很快想起这段代码的用途。代码注释不仅方便程序员自己回忆起以前代码的用途&#xff0c;还可以帮助其他程序员很快的读懂…

[Leedcode][JAVA][第287题][寻找重复数][HashSet][二分查找][快慢指针]

【问题描述】[中等] 给定一个包含 n 1 个整数的数组 nums&#xff0c;其数字都在 1 到 n 之间&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。假设只有一个重复的整数&#xff0c;找出这个重复的数。输入: [1,3,4,2,2] 输出: 2说明&#xff1a…

html:(6):body标签和p标签

<body>标签&#xff0c;网页上显示的内容放在这里 还记得body标签吗&#xff0c;在上一章节我们简单介绍过&#xff1a;在网页上要展示出来的页面内容一定要放在body标签中。如下图是一个新闻文章的网页。 在浏览器中的显示效果&#xff1a; <!DOCTYPE HTML> <h…

[Leedcode][JAVA][第974题][和可被K整除的子数组][前缀和][HashSet]

【问题描述】[中等] 给定一个整数数组 A&#xff0c;返回其中元素之和可被 K 整除的&#xff08;连续、非空&#xff09;子数组的数目。示例&#xff1a;输入&#xff1a;A [4,5,0,-2,-3,1], K 5 输出&#xff1a;7 解释&#xff1a; 有 7 个子数组满足其元素之和可被 K 5 …

html:(7):了解hx标签和加强语气

了解<hx>标签&#xff0c;为你的网页添加标题 文章的段落用<p>标签&#xff0c;那么文章的标题用什么标签呢&#xff1f;在本节我们将使用<hx>标签来制作文章的标题。 标题标签一共有6个&#xff0c;h1、h2、h3、h4、h5、h6分别为一级标题、二级标题、三级标…

html:(8):span标签和q标签

使用<span>标签为文字设置单独样式 这一小节讲解<span>标签&#xff0c;我们对<em>、<strong>、<span>这三个标签进行一下总结&#xff1a; 1. <em>和<strong>标签是为了强调一段话中的关键字时使用&#xff0c;它们的语义是强调。…

cs20_1-1

1. 基本特点 1.1 save computation(惰性运行) x 2 y 3 add_op tf.add(x, y) mul_op tf.multiply(x, y) useless tf.multiply(x, add_op) pow_op tf.pow(add_op, mul_op) with tf.Session() as sess:z sess.run(pow_op) 如上&#xff0c;因为sess.run(pow_op)不需要用到u…

[剑指offer][JAVA]面试题第[03]题[数组中的重复数字][HashSet]

【问题描述】[数组中的重复数字][简单] 找出数组中重复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0&#xff5e;n-1 的范围内。数组中某些数字是重复的&#xff0c;但不知道有几个数字重复了&#xff0c;也不知道每个数字重复了几次。请找出数组中任意一个重复的…

德国超级计算机中心,德国:强化人工智能能力建设 加大高性能计算网络投资...

图片来源&#xff1a;德国马克斯普朗克智能系统研究所德国2020年更新《国家人工智能战略》&#xff0c;在原先30亿欧元基础上再增加20亿欧元支持德国人工智能研究。德国科学联席会议决定投入1.33亿欧元&#xff0c;继续加强对人工智能能力中心和“高校教育的人工智能”进行资助…

html:(9):blockquote引用和br换行

<blockquote>标签&#xff0c;长文本引用 <blockquote>的作用也是引用别人的文本。但它是对长文本的引用&#xff0c;如在文章中引入大段某知名作家的文字&#xff0c;这时需要这个标签。 等等&#xff0c;上一节<q>标签不是也是对文本的引用吗&#xff1f;不…

K3CLOUD数据权限授权

1.定义角色&#xff0c;把用户放入角色内 2.设置数据规则 3.设置业务对象功能授权 转载于:https://www.cnblogs.com/RogerLu/p/10370347.html

html:(10):添加空格和hr

为你的网页中添加一些空格 在上一节的例子&#xff0c;我们已经讲解过在html代码中输入空格、回车都是没有作用的。要想输入空格&#xff0c;必须写入 。 语法&#xff1a; 在html代码中输入空格是不起作用的&#xff0c;如下代码。 在浏览中显示&#xff0c;还是没有空格效果…

[剑指offer][JAVA]面试题第[04]题[二维数中的查找][数组]

【问题描述】[中等] 在一个 n * m 的二维数组中&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该整数。示例:现有矩阵 matrix …

微机计算机原理姚向华课后答案,微型计算机操作系统

1. 详尽剖析Mac OS X内部工作原理的具体细节。 2. 揭示Mac OS X及其组件的核心体系结构和实现。 3. 以一种面向实现的方法介绍Mac OS X系统。 4. 透彻解释Mac OS X的众多用户级和内核级IPC机制的工作原理&#xff0c;并且提供足够的知识和示例&#xff0c;可以满足各个层次的读…

TokenFlow详解

https://github.com/omerbt/TokenFlow/issues/25 https://github.com/omerbt/TokenFlow/issues/31 https://github.com/omerbt/TokenFlow/issues/32 https://github.com/eps696/SDfu register_extended_attention_pnp1. 为所有BasicTransformerBlock layer的attn1重构forward2.…

html:(11):address和code标签

<address>标签&#xff0c;为网页加入地址信息 一般网页中会有一些网站的联系地址信息需要在网页中展示出来&#xff0c;这些联系地址信息如公司的地址就可以<address>标签。也可以定义一个地址&#xff08;比如电子邮件地址&#xff09;、签名或者文档的作者身份…

Java虚拟机(JVM)面试题大集合

Java虚拟机&#xff08;JVM&#xff09;Java内存区域说一下 JVM 的主要组成部分及其作用&#xff1f;说一下 JVM 运行时数据区深拷贝和浅拷贝说一下堆栈的区别&#xff1f;队列和栈是什么&#xff1f;有什么区别&#xff1f;HotSpot虚拟机对象探秘对象的创建为对象分配内存处理…

crossdomain.xml配置不当的利用和解决办法

00x1: 今天在无聊的日站中发现了一个flash小站&#xff0c;点进crossdomain.xml一看&#xff0c;震惊 本屌看到这个*就发觉事情不对 百度一下&#xff0c;这是一个老洞&#xff0c;配置不当能引起各种问题就算能远程加载恶意的swf文件&#xff0c;(swf是flash专用后缀文件常用于…

html:(12):pre和ul-li

使用<pre>标签为你的网页加入大段代码 在上节中介绍加入一行代码的标签为<code>&#xff0c;但是在大多数情况下是需要加入大段代码的&#xff0c;如下图&#xff1a; 怎么办&#xff1f;不会是每一代码都加入一个<code>标签吧&#xff0c;没有这么复杂&…

[Leedcode][JAVA][第394题][字符串解码][栈][类型转换]

【问题描述】[中等] 给定一个经过编码的字符串&#xff0c;返回它解码后的字符串。编码规则为: k[encoded_string]&#xff0c;表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。你可以认为输入字符串总是有效的&#xff1b;输入字符串中没有额外的空…