给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
解题方法一:二分查找法
/**********JavaScript**************/
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number}
*/
var findMedianSortedArrays = function(nums1, nums2) {
// 二分查找 先找到较短元素分割线的位置
// 防止
// 1、较短的数组,在分割线左边没有元素
// 2、较短的数组,在分割线右边没有元素
if(nums1.length > nums2.length) {
let arr = nums1;
nums1 = nums2;
nums2 = arr
}
var m = nums1.length,
n = nums2.length;
// 分割线左边的元素的数量合计,需要满足
var totalLeft = Math.floor((m + n + 1)/2);
var left = 0, // 左指针
right = m; // 右指针
while(left < right){
// 取中间位置,由于是向下取整,为了防止i=0 因此right - left + 1
// i 是nums1分割线左边元素的个数(也是nums1分割线的位置),
// j是nums2分割线左边元素的个数(也是nums2分割线的位置),
var i = left + Math.floor((right - left + 1) / 2);
var j = totalLeft - i;
// 需要找到满足
//1、 nums1分割线左侧元素的值 <= nums2分割线右侧元素的值,即 nums1[i-1] <= nums2[j]
//2、 nums2分割线左侧元素的值 <= nums1分割线右侧元素的值,即 nums1[j-1] <= nums2[i]
if ( nums1[i-1] > nums2[j]) {
// 当 nums1分割线左侧元素的值 > nums2分割线右侧元素的值,
// 说明分割线太靠右边,因此右指针往左挪, [left, i-1]
right = i - 1;
} else {
// 否则左指针往右挪, [i, right]
left = i;
}
}
var i = left, // nums1分割线
j = totalLeft - left; // nums2分割线
// nums1分割线左侧元素的值; 如果nums1分割线左侧没有元素(i = 0),给nums1LeftMax设置无穷小
var nums1LeftMax = i === 0 ? -Infinity : nums1[i - 1];
// nums1分割线右侧元素的值; 如果nums1分割线右侧没有元素(i = m),给nums1RightMax设置无穷大
var nums1RightMin = i === m ? Infinity : nums1[i];
// nums2分割线左侧元素的值; 如果nums2分割线左侧没有元素(j = 0),给nums2LeftMax设置无穷小
var nums2LeftMax = j === 0 ? -Infinity : nums2[j - 1];
// nums2分割线右侧元素的值; 如果nums2分割线右侧没有元素(j = m),给nums1RightMax设置无穷大
var nums2RightMin = j === n ? Infinity : nums2[j];
// 奇数 取nums1、num2分割线左侧最大值即可
if ((m + n) % 2 == 1) {
return Math.max(nums1LeftMax, nums2LeftMax);
} else{
// 偶数 (nums1、num2分割线左侧最大值 + nums1、num2分割线右侧最小值) / 2
return (Math.max(nums1LeftMax, nums2LeftMax) + Math.min(nums1RightMin, nums2RightMin)) / 2;
}
};