题目描述
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数。
算法的时间复杂度应该为 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
思路&js代码
1、双指针
var findMedianSortedArrays = function(a, b) {
if (a.length > b.length) {
[a, b] = [b, a]; // 保证下面的 i 可以从 0 开始枚举
}
const m = a.length, n = b.length;
a = [-Infinity, ...a, Infinity];
b = [-Infinity, ...b, Infinity];
// 枚举 nums1 有 i 个数在第一组
// 那么 nums2 有 j = (m + n + 1) / 2 - i 个数在第一组
let i = 0, j = Math.floor((m + n + 1) / 2);
while (true) {
if (a[i] <= b[j + 1] && a[i + 1] > b[j]) { // 写 >= 也可以
const max1 = Math.max(a[i], b[j]); // 第一组的最大值
const min2 = Math.min(a[i + 1], b[j + 1]); // 第二组的最小值
return (m + n) % 2 ? max1 : (max1 + min2) / 2;
}
i++; // 继续枚举
j--;
}
};2、二分查找
var findMedianSortedArrays = function(a, b) {
if (a.length > b.length) {
[a, b] = [b, a];
}
const m = a.length, n = b.length;
a = [-Infinity, ...a, Infinity];
b = [-Infinity, ...b, Infinity];
// 循环不变量:a[left] <= b[j+1]
// 循环不变量:a[right] > b[j+1]
let left = 0, right = m + 1;
while (left + 1 < right) { // 开区间 (left, right) 不为空
const i = Math.floor((left + right) / 2);
const j = Math.floor((m + n + 1) / 2) - i;
if (a[i] <= b[j + 1]) {
left = i; // 缩小二分区间为 (i, right)
} else {
right = i; // 缩小二分区间为 (left, i)
}
}
// 此时 left 等于 right-1
// a[left] <= b[j+1] 且 a[right] > b[j'+1] = b[j],所以答案是 i=left
const i = left;
const j = Math.floor((m + n + 1) / 2) - i;
const max1 = Math.max(a[i], b[j]);
const min2 = Math.min(a[i + 1], b[j + 1]);
return (m + n) % 2 ? max1 : (max1 + min2) / 2;
};