LeetCode 力扣: 寻找两个正序数组的中位数 (Javascript)
LeetCode力扣双指针题目
主要提供了力扣热题第四题,使用js,复杂度O(log(m+n))
,寻找两个正序数组的中位数。
题目解析
题目要求在两个已排序数组 nums1
和 nums2
中找到它们的中位数。为了满足时间复杂度要求 O(log (m+n))
,可以采用双指针的方法合并这两个数组,然后计算中位数。
思路
首先,代码检查 nums1
和 nums2
的长度,确保 nums1 总是较短的数组。如果 nums1
的长度大于 nums2
,则通过递归调用 findMedianSortedArrays
函数,将它们的顺序反转,以确保 nums1
始终是较短的数组。
获取 nums1
和 nums2
的长度,分别赋值给 x 和 y。
初始化两个指针 low
和 high
,它们将用于执行二分查找。low
初始为0,high
初始为 x,即 nums1
的长度。
进入一个循环,循环条件是 low
小于等于 high
。
在每次循环迭代中,计算 partitionX
和 partitionY
,这两个值将用于将数组分成左右两部分。partitionX
表示将 nums1
分成左右两部分的分界点,而 partitionY
表示将 nums2
分成左右两部分的分界点。这些分界点是通过位运算和数组长度计算得出的。
根据分界点,获取左右两部分的最大值和最小值。maxX
和 minX
表示 nums1
中左右两部分的最大值和最小值,而 maxY
和 minY
表示 nums2
中左右两部分的最大值和最小值。
接着,代码检查最大值和最小值是否满足中位数的条件,即 maxX <= minY
和 maxY <= minX
。如果满足这些条件,说明找到了中位数的位置。
如果总元素个数是偶数((x + y) % 2 === 0)
,则中位数是左右两部分的最大值和最小值的平均数;如果总元素个数是奇数,中位数是最大值中的较大值。
如果没有找到中位数的位置,根据情况更新 low
或 high
,以继续二分查找。
最终,如果循环结束后仍然没有找到中位数的位置,代码会抛出一个错误,表示输入的数组不是有序的。
代码
function findMedianSortedArrays(nums1, nums2) {
if (nums1.length > nums2.length) {
return findMedianSortedArrays(nums2, nums1);
}
const x = nums1.length;
const y = nums2.length;
let low = 0;
let high = x;
while (low <= high) {
const partitionX = (low + high) >> 1;
const partitionY = ((x + y + 1) >> 1) - partitionX;
const maxX = (partitionX === 0) ? Number.NEGATIVE_INFINITY : nums1[partitionX - 1];
const maxY = (partitionY === 0) ? Number.NEGATIVE_INFINITY : nums2[partitionY - 1];
const minX = (partitionX === x) ? Number.POSITIVE_INFINITY : nums1[partitionX];
const minY = (partitionY === y) ? Number.POSITIVE_INFINITY : nums2[partitionY];
if (maxX <= minY && maxY <= minX) {
if ((x + y) % 2 === 0) {
return (Math.max(maxX, maxY) + Math.min(minX, minY)) / 2;
} else {
return Math.max(maxX, maxY);
}
} else if (maxX > minY) {
high = partitionX - 1;
} else {
low = partitionX + 1;
}
}
throw new Error("Input arrays are not sorted.");
}
代码解析
((x + y + 1) >> 1) - partitionX
这段代码是什么意思
((x + y + 1) >> 1) - partitionX
这段代码用于计算 partitionY
,即将第二个数组 nums2
分成左右两部分的分界点。让我解释一下这个表达式的含义:
x
是第一个数组nums1
的长度。y
是第二个数组nums2
的长度。partitionX
是将第一个数组nums1
分成左右两部分的分界点。
现在来逐步解释这个表达式:
-
x + y + 1
:首先,将两个数组的长度相加,并加1。这是因为在计算中位数时,需要考虑总的元素个数是否为奇数还是偶数。 -
>> 1
:然后,对上述结果进行右移一位,相当于除以2。这是因为中位数是将数组分成两部分,左半部分和右半部分,因此需要将总长度分为两半。 -
- partitionX
:最后,从上述结果中减去partitionX
。partitionX
表示将第一个数组nums1
分成左右两部分的分界点。减去partitionX
的目的是确定第二个数组nums2
分成左右两部分的分界点partitionY
。
这个表达式的目的是计算如何将两个数组分成左右两部分,以满足中位数的条件。它考虑了两个数组的长度,以确保正确计算中位数的位置。在这种二分查找算法中,partitionX
和 partitionY
的计算是关键,因为它们指导着如何在两个数组中查找中位数的位置。
if (maxX <= minY && maxY <= minX) {
这段代码是什么意思
maxX
表示第一个数组nums1
中分界点partitionX
左侧部分的最大值,或者在partitionX
为0时为负无穷大。minY
表示第二个数组nums2
中分界点partitionY
右侧部分的最小值,或者在partitionY
为y
时为正无穷大。maxY
表示第二个数组nums2
中分界点partitionY
左侧部分的最大值,或者在partitionY
为0时为负无穷大。minX
表示第一个数组nums1
中分界点partitionX
右侧部分的最小值,或者在partitionX
为x
时为正无穷大。
这个条件 maxX <= minY && maxY <= minX
检查以下情况是否成立:
-
maxX
小于等于minY
:即第一个数组左侧部分的最大值小于等于第二个数组右侧部分的最小值。 -
maxY
小于等于minX
:即第二个数组左侧部分的最大值小于等于第一个数组右侧部分的最小值。
如果这两个条件都成立,意味着已找到中位数的位置,因为左侧部分的元素都小于或等于右侧部分的元素。这是中位数的定义。
在满足这些条件的情况下,根据总元素个数是奇数还是偶数,代码返回相应的中位数值。如果总元素个数是偶数,中位数是左右两部分的最大值和最小值的平均数;如果总元素个数是奇数,中位数是最大值中的较大值。
这个条件判断是整个算法中的核心,用于确定中位数的位置。如果条件不成立,代码将根据情况更新 low
或 high
,以继续二分查找,直到找到中位数的位置
总结
希望本文会对你有所帮助,如果有任何疑问可以留言与我沟通。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!