4. 寻找两个正序数组的中位数
给定两个大小分别为 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
解法一:二分算法
解题思路:这题可以用二分算法,首先就是先确认中位数k的位置,如果是基数中位数就是两个数组和除以2向上取整个位数,索引要减一,偶数就是基数加一加基数除以二,确认中位数之后,然后两个数组每次减去二分之一中位数,加入算出nums1的前二分之k的位置为a,nums2的前二分之k为位置b=,如果nums1[a] <= nums2[b]那么k在nums[a]之后,在nums2[b]之前,反之就是在nums[a]之前,nums2[b]之后,代码如下:
var findMedianSortedArrays = function(nums1, nums2) {
//现获取数组总长度
let leng = nums1.length + nums2.length;
//获取中间位置,这里是索引从1开始,第几位,如果是获取数组索引需要减一
let m = (leng + 1) >> 1;
//查找第m位数
let a = findk(nums1,nums2,0,0,m);
//如果数组是偶数就再取下一位,求和
if(leng % 2 == 1) return a;
let b = findk(nums1,nums2,0,0,m + 1);
return (a + b) / 2;
};
let findk = function(data1,data2,i,j,k){
//当第一个数组是空时,就返回第二个数组的第k位,因为上面k索引是从1开始,所以需要减一
if(i == data1.length) return data2[j + k - 1];
//同上
if(j == data2.length) return data1[i + k - 1];
当k等于1,说明两个数组都只剩一,谁小取谁
if(k == 1) return data1[i] < data2[j] ? data1[i] : data2[j];
//因为数组会有不够减的情况,所以谁小取谁的个数
let a = Math.min(parseInt(k/2),data1.length - i);
//第一个数组取几个剩下的在b里取,因为数组2也会有不够取的情况,所以取小
let b = Math.min(k - a, data2.length - j);
//因为会出现数组2不够取,所以需要重置a
a = k - b;
//当data1二分之k的位置小于data2二分之k的位置的时候,k在数组data1[k/2]之后和data2[k/2]之前
if(data1[i + a - 1] <= data2[j + b - 1]){
//去掉data1[k/2]之前的位置,更新data1的其实位置
return findk(data1,data2,i + a,j,k - a);
}
此时k在data1[k/2]之前和data2[k/2]之前后,需要更新data2的其实位置
return findk(data1,data2,i,j + b,k - b);
}
解法2:归并算法的合并操作
解题思路:将两个有序数组合并成一个数组,谁小谁入栈,然后求中间位置,代码如下:
var findMedianSortedArrays = function(nums1, nums2) {
//定义新的数组接收合并后的数组
let data = [];
//直到两个数组都出栈了,就结束
while(nums1.length > 0 || nums2.length > 0){
//当数组2位空,谁小谁出栈
if(nums2.length < 1 || nums1[0] <= nums2[0]){
data.push(nums1.shift())
} else if(nums1.length < 1 || nums1[0] > nums2[0]){
data.push(nums2.shift());
}
}
let leng = data.length;
let m = parseInt(leng/2);
//判断数组长度是基数还是偶数
if(leng % 2 == 1){
return data[m]
} else {
return (data[m] + data[m - 1]) / 2;
}
};