本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
输入: nums1 = [1,3], nums2 = [2]
输出: 2.00000
解释: 合并数组 = [1,2,3] ,中位数 2
题目思路
思路一
第
k小数求解,那么前边必然有两个k/2个数,此题中我们在两个数组中分别取前k/2个数,比较上下两个数组第k/2个数,排除掉较小的数所在两者中较小的那k/2个数,那么下次我们就是要求第k-k/2小数,仍然与开头的逻辑类似,我们每次都会删除不符合条件的元素,直到最后要去第1个小数,那么我们比较两个数组的第一个值即可,这里我们考虑一个特殊情况,如果k/2超过数组的长度,那么我们就比较第一个length - 1和第二个k/2这两个数,如果length - 1所指的数大于k/2,那么我们下一轮寻找k-k/2小数,否则下一轮寻找k-(length - 1)小数,这里我们可以做一个特殊处理,将num1永远指向最小的一个,这样当num1的length为0的时候,我们直接返回num2[k-1]即可
var findMedianSortedArrays = function(num1, num2) {
const m = num1.length
const n = num2.length
const totalLength = m + n
// 第k小数,奇数使用
const k1 = (totalLength + 1) >> 1
// 第k+1小数,偶数使用
const k2 = (totalLength + 2) >> 1
return (getKth(num1, num2, k1) + getKth(num1, num2, k2)) / 2
}
function getKth (num1, num2, k) {
if (num1.length > num2.length) {
[num1, num2] = [num2, num1]
}
const m = num1.length
const n = num2.length
if (num1.length === 0) return num2[k-1]
if (k === 1) return Math.min(num1[0] || 0, num2[0] || 0)
let halfK = k >> 1
let i = Math.min(halfK - 1, m - 1)
let j = Math.min(halfK - 1, n - 1)
if (num1[i] < num2[j]) {
return getKth(num1.slice(i + 1), num2, k - (i + 1))
} else {
return getKth(num1, num2.slice(j + 1), k - (j + 1))
}
}
思路二
我们先进行合并数组并排序,然后再取长度的一半,如一半值带小数点,说明长度为奇数,取一半值向下取整的下标值就为中间值,如果长度值不带小数点,说明长度为偶数,取数组的长度值下标值加数组的长度值下标减一值除2,便是中间值
var findMedianSortedArrays = function(nums1, nums2) {
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
var all = [...nums1, ...nums2].sort(compare);
var allLength = all.length;
var midIndex = allLength / 2;
if(String(midIndex).includes(".")) {
return all[Math.floor(midIndex)]
} else {
return (all[midIndex] + all[midIndex - 1]) / 2
}
};