给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
解题思路
看到这题后的第一想法就是利用两个指针,再用归并成一个数组在取其中位数。
const findMedianSortedArrays = function(nums1, nums2) {let index1 = 0let index2 = 0let result = []while(index1<nums1.length && index2<nums2.length){if(nums1[index1]>nums2[index2]){result.push(nums2[index2])index2++}else{result.push(nums1[index1])index1++}}if(index1===nums1.length){result = result.concat(nums2.slice(index2))}else{result = result.concat(nums1.slice(index1))}let length = result.lengthif(length/2===parseInt(length/2)){return (result[length/2]+result[length/2-1])/2}else{return result[parseInt(length/2)]}}
Go
go版本,没有什么大的区别。go中的数组不能push只能预先分配大小,然后根据索引设置值。
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {index1,index2,k := 0,0,0m,n := len(nums1),len(nums2)result := make([]int,m+n)var res float64for ;k<m+n;k++ {if index1 < m && index2 < n {if nums1[index1]>nums2[index2] {result[k] = nums2[index2]index2++}else{result[k] = nums1[index1]index1++}}else if index1<m {result[k] = nums1[index1]index1++}else{result[k] = nums2[index2]index2++}}if len(result)%2==0 {res = float64(result[len(result)/2] + result[len(result)/2-1])/2}else{res = float64(result[len(result)/2])}return res}
Rust
rust版本。
impl Solution {
pub fn find_median_sorted_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
let mut index1 = 0;
let mut index2 = 0;
let mut m = nums1.len();
let mut n = nums2.len();
let mut result = vec![];
while index1 < m && index2 < n {
if nums1[index1] > nums2[index2] {
result.push(nums2[index2]);
index2 += 1;
} else {
result.push(nums1[index1]);
index1 += 1;
}
}
if index1 == m {
while index2 < n {
result.push(nums2[index2]);
index2 += 1;
}
} else {
while index1 < m {
result.push(nums1[index1]);
index1 += 1;
}
}
let length = result.len();
if length % 2 == 0 {
(result[(length / 2)] as f64 + result[(length / 2) - 1] as f64) / 2 as f64
} else {
result[(length / 2)] as f64
}
}
}
附加题
题目的条件是使时间复杂度降到O(log(m+n)),所以这才让这道题变成一道困难题。根据这个复杂度我们应该使用二分查找的方法。
二分查找的思路是这样的

有两种情况,一种是两个数组的元素数量是奇数时,我们就会取左侧最大数。另一种偶数时,我们取左侧最大右侧最小值的平均数。这条分割线的规则就是 左右两边的元素的数量要相等或者左边多一个,并且左边的数要全部小于右边的数。
上面四种是特殊情况有的时候线的两端是没有数字的,所以在这种情况要对最后取数的时候进行判断,如果遇到没有数的情况就要对其赋值为最大值和最小值
Number.MIN_SAFE_INTEGER以及Number.MAX_SAFE_INTEGER
const findMedianSortedArrays = function (num1, num2) {
if (num1.length > num2.length) {
let temp = num1
num1 = num2
num2 = temp
}
let m = num1.length
let n = num2.length
//分割线左边的所有元素需要满足的个数 m + (n - m + 1)/2
let totalLeft = parseInt((m + n + 1) / 2)
//在num1的区间[0, m]里查找恰当的分割线
//使得 num1[i-1]<=num2[j] && num1[j-1]<=num2[i]
let left = 0
let right = m
while (left < right) {
let i = left + parseInt((right - left + 1) / 2)
let j = totalLeft - i
if (num1[i - 1] > num2[j]) { // 违反上面的条件 所以这样写
//下一轮搜索区间 [left, i-1]
right = i - 1
} else {
//下一轮搜素区间 [i, right]
left = i
}
}
let i = left
let j = totalLeft - i
let nums1LeftMax = i === 0 ? Number.MIN_SAFE_INTEGER : num1[i - 1]
let nums1RightMin = i === m ? Number.MAX_SAFE_INTEGER : num1[i]
let nums2LeftMax = j === 0 ? Number.MIN_SAFE_INTEGER : num2[j - 1]
let nums2RightMin = j === n ? Number.MAX_SAFE_INTEGER : num2[j]
if ((m + n) % 2 === 1) {
console.log(nums1LeftMax, nums2LeftMax)
return Math.max(nums1LeftMax, nums2LeftMax)
} else {
return (Math.max(nums1LeftMax, nums2LeftMax) + Math.min(nums1RightMin, nums2RightMin)) / 2
}
}
