题目
给定两个大小为 m 和 n 的有序数组 nums1
和 nums2
。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1
和 nums2
不会同时为空。
一. 连接数组后排序
将两个数组连接起来后进行排序,返回排序后的数组的中位数。
js实现
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number}
*/
var findMedianSortedArrays = function(nums1, nums2) {
var result = nums1.concat(nums2)
result.sort((a, b) => a - b)
if (result.length % 2) {
return result[(result.length-1)/2]
} else {
return (result[result.length/2-1] + result[result.length/2]) / 2
}
};
复杂度分析
时间复杂度:O((m+n)*log(m+n))
空间复杂度:O(m+n)
测试结果
✔ Accepted
✔ 2085/2085 cases passed (156 ms)
✔ Your runtime beats 91.84 % of javascript submissions
✔ Your memory usage beats 49.74 % of javascript submissions (39.5 MB)
二. 迭代去除最值
两个数组的中位数与去掉最小值和最大值之后的两个数组相等,当其中一个数组为空时,返回另一个数组的中位数即可。
js实现
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number}
*/
var findMedianSortedArrays = function(nums1, nums2) {
while (nums1.length + nums2.length > 2 && nums1.length && nums2.length) {
var startd1 = true
if (nums1[0] > nums2[0]) {
startd1 = false
}
var endd1 = true
if (nums1[nums1.length-1] < nums2[nums2.length-1]) {
endd1 = false
}
if (startd1) {
nums1.shift()
} else {
nums2.shift()
}
if (endd1) {
nums1.pop()
} else {
nums2.pop()
}
}
if (!nums1.length) {
if (nums2.length%2) {
return nums2[(nums2.length-1) / 2]
} else {
return (nums2[nums2.length/2-1] + nums2[nums2.length/2]) / 2
}
}
if (!nums2.length) {
if (nums1.length%2) {
return nums1[(nums1.length-1) / 2]
} else {
return (nums1[nums1.length/2-1] + nums1[nums1.length/2]) / 2
}
}
return (nums1[0] + nums2[0]) / 2
};
复杂度分析
时间复杂度:O(min(m, n))
空间复杂度:O(1)
测试结果
✔ Accepted
✔ 2085/2085 cases passed (188 ms)
✔ Your runtime beats 63.95 % of javascript submissions
✔ Your memory usage beats 97.83 % of javascript submissions (38.5 MB)
三. 中位数定义与二分查找结合
根据中位数的定义,将两个数组各自从某处划分为左右两部分,如果两个数组的左边部分两数组的长度之和与右边部分两数组的长度之和相等,且两个数组左边部分的最大值不大于右边部分的最小值,则中位数为左边最大值与右边最小值的平均。
由于左右部分长度相等,因此我们只需要确定第一个数组的划分位置,使用二分法查找此位置即可。
js实现
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number}
*/
var findMedianSortedArrays = function(nums1, nums2) {
if (nums1.length > nums2.length) {
var temp = nums1
nums1 = nums2
nums2 = temp
// [m, n] = [n, m]
}
var m = nums1.length
var n = nums2.length
// 定义数组1的左右边界
var left = 0
var right = m
// 一半长度
var half = Math.floor((m + n + 1) / 2)
while (left <= right) {
var i = Math.floor((left + right) / 2)
var j = half - i
if (i < right && nums1[i] < nums2[j-1]) {
left = i + 1
} else if (i > left && nums2[j] < nums1[i-1]) {
right = i - 1
} else {
var leftMax
if (i === 0) {
leftMax = nums2[j-1]
} else if (j === 0) {
leftMax = nums1[i-1]
} else {
leftMax = Math.max(nums1[i-1], nums2[j-1])
}
if ((m + n) % 2) {
return leftMax
}
var rightMin
if (i === m) {
rightMin = nums2[j]
} else if (j === n) {
rightMin = nums1[i]
} else {
rightMin = Math.min(nums1[i], nums2[j])
}
return (leftMax + rightMin) / 2
}
}
};
复杂度分析
时间复杂度:O(log(min(m, n)))
空间复杂度:O(1)
测试结果
✔ Accepted
✔ 2085/2085 cases passed (124 ms)
✔ Your runtime beats 99.18 % of javascript submissions
✔ Your memory usage beats 94.52 % of javascript submissions (38.8 MB)