topic
Given two positive order (from small to large) arrays nums1 and nums2 with sizes m and n respectively. Please find and return the median of these two ordinal arrays.
The time complexity of the algorithm should be O(log (m+n)).
Example 1:
Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: Combined array = [1,2,3], median 2
Example 2:
Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: Combined array = [1,2,3,4], median (2 + 3) / 2 = 2.5
hint:
- nums1.length == m
- nums2.length == n
- 0 <= m <= 1000
- 0 <= n <= 1000
- 1 <= m + n <= 2000
- -106 <= nums1[i], nums2[i] <= 106
problem solving ideas
This problem can be transformed into a problem of finding the Kth decimal of two sorted arrays, where K is half the total length of the two arrays. First compare the median of the two arrays, compare the K value with the subscript of the median, and determine the search range of the smaller array. Then perform a binary search in the smaller array, determine the subscript of the other array according to the subscript of the median, compare the values at the corresponding positions of the two arrays, and adjust the search range of the smaller array according to the comparison result. Repeat the above steps until the Kth smallest number is found. Finally, the median is calculated according to the parity of K.
Time complexity: O(log(m+n)).
the code
c++
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size(), n = nums2.size();
// 确保 nums1 的长度小于等于 nums2,如果不是,则交换两个数组
if (m > n) {
return findMedianSortedArrays(nums2, nums1);
}
// 初始化 LMax1, LMax2, RMin1, RMin2, c1, c2, lo 和 hi
int LMax1, LMax2, RMin1, RMin2, c1, c2, lo = 0, hi = 2 * m;
// 二分查找
while (lo <= hi) {
// 计算 c1 和 c2
c1 = (lo + hi) / 2;
c2 = m + n - c1;
// 计算 LMax1, LMax2, RMin1 和 RMin2
LMax1 = (c1 == 0) ? INT_MIN : nums1[(c1 - 1) / 2];
RMin1 = (c1 == 2 * m) ? INT_MAX : nums1[c1 / 2];
LMax2 = (c2 == 0) ? INT_MIN : nums2[(c2 - 1) / 2];
RMin2 = (c2 == 2 * n) ? INT_MAX : nums2[c2 / 2];
// 如果 LMax1 大于 RMin2,则应该减小 c1,因为 nums1 部分太大了
if (LMax1 > RMin2) {
hi = c1 - 1;
}
// 如果 LMax2 大于 RMin1,则应该增大 c1,因为 nums1 部分太小了
else if (LMax2 > RMin1) {
lo = c1 + 1;
}
// 找到了合适的位置,结束循环
else {
break;
}
}
// 返回中位数
return (max(LMax1, LMax2) + min(RMin1, RMin2)) / 2.0;
}
};
golang
package main
import "math"
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
m, n := len(nums1), len(nums2)
// 保证第一个数组较短,这样时间复杂度会更优
if m > n {
nums1, nums2, m, n = nums2, nums1, n, m
}
// lo 和 hi 分别表示在 nums1 中切割的位置
lo, hi := 0, 2*m
// 在 nums1 中切割位置为 c1,nums2 中切割位置为 c2
for lo <= hi {
c1 := (lo + hi) / 2
c2 := m + n - c1
var LMax1, RMin1, LMax2, RMin2 int
// 计算 LMax1、RMin1、LMax2、RMin2
if c1 == 0 {
LMax1 = int(math.Inf(-1))
} else if c1%2 == 1 {
LMax1 = nums1[(c1-1)/2]
} else {
LMax1 = nums1[(c1-1)/2]
}
if c1 == 2*m {
RMin1 = int(math.Inf(1))
} else {
RMin1 = nums1[c1/2]
}
if c2 == 0 {
LMax2 = int(math.Inf(-1))
} else if c2%2 == 1 {
LMax2 = nums2[(c2-1)/2]
} else {
LMax2 = nums2[(c2-1)/2]
}
if c2 == 2*n {
RMin2 = int(math.Inf(1))
} else {
RMin2 = nums2[c2/2]
}
// 如果 LMax1 大于 RMin2,则应该减小 c1,因为 nums1 部分太大了
if LMax1 > RMin2 {
hi = c1 - 1
}
// 如果 LMax2 大于 RMin1,则应该增大 c1,因为 nums1 部分太小了
if LMax2 > RMin1 {
lo = c1 + 1
}
// 找到了合适的位置,结束循环
if LMax1 <= RMin2 && LMax2 <= RMin1 {
break
}
}
// 返回中位数
return float64((math.Max(float64(LMax1), float64(LMax2)) + math.Min(float64(RMin1), float64(RMin2))) / 2.0)
}