题目
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
思路 O(log(min(m,n))
left_part | right_part A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1] B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
找到 i,j 使得 条件1满足:
even: size(left_part)+size(right_part)=i+j =(m+n)/2
odd: size(left_part)+size(right_part)=i+j =(m+n+1)/2
&&
这时,就有
even:
odd:
特殊情况
i=m left_part | right_part A[0], A[1], ..., A[m-1] | B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
even:
odd:
i=0 left_part | right_part | A[0], A[1], ..., A[m-1] B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
even:
odd:
特殊情况 m=n
j=n
j=n left_part | right_part | A[0], A[1], ..., A[m-1] B[0], B[1], ..., B[n-1] |
even:
j=0
j=0 left_part | right_part A[0], A[1], ..., A[m-1] | | B[0], B[1], ..., B[n-1]
even:
接下来的问题是如何找到合适的 i ,j,根据 size(left_part)+size(right_part)=i+j =(m+n+1)/2 可以得到i,j之间约束,此时,而约束n>=m的意义就在于对于任何i,j都在[0,n]得区间内。因此在[0,m] 闭区间上搜索i,使得 满足。
不考虑 size(left_part)+size(right_part)=i+j =(m+n)/2 是因为 当m+n是偶数时,(int)(m+n)/2 = (int)(m+n+1)/2
对于任意一个 ,有以下3种情况
- ,说明 i 太大 ,i应该比当前值要小,减小A[i-1]的值,同时根据 ,j增大,增大B[j],并且搜索区间减少为
- ,说明 i 太小 ,i应该比当前值要大,并且搜索区间减少为
- 其他情况,就是找到合适的i,j
使用二分法,设定初始区间为[imin,imax]=[0,m],判断值为区间中值 i= (imax-imin)/2+imin
有以下情况
0<i(确保A[i-1]存在),A[i-1]> B[j] 这时使 [imin,imax]=[imin,i-1]
i<m(确保A[i]存在),B[j1]> A[i] 这时使 [imin,imax]=[i+1,imax]
其他情况就是找到合适的i,j
随着搜索区间变化,其中有两种极端的收敛情况
[imin,imax] = [0,0] 和 [imin,imax]=[m,m] 对应上面两种特殊情况,因此使用二分法并且把初始区间设定为闭区间,即可自动得到这两种结果。此时的i=0 或者 i=m,j=0或者j=n ,根据i , j可以区分出特殊情况
class Solution {
public:
double bsearch(vector<int>& A, vector<int>& B) {
int m = A.size();
int n = B.size();
int imin = 0, imax = m, half_len = (m + n + 1) / 2;
int i, j, max_of_left, min_of_right;
while (imin <= imax) {
i = (imin + imax) / 2;
j = half_len - i;
if (i<m && B[j - 1]>A[i]) { imin = i + 1; }
else if (i > 0 && A[i - 1] > B[j]) { imax = i - 1; }
else {
if (i == 0) { max_of_left = B[j - 1]; }
else if (j == 0) { max_of_left = A[i - 1]; }
else { max_of_left = max(A[i - 1], B[j - 1]); }
if ((m + n) % 2 == 1) { return max_of_left; }
if (i == m) { min_of_right = B[j]; }
else if (j == n) { min_of_right = A[i]; }
else { min_of_right = min(A[i], B[j]); }
return double((max_of_left + min_of_right)) / 2;
}
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int nums1_size = nums1.size();
int nums2_size = nums2.size();
if (nums1_size > nums2_size) {return bsearch(nums2, nums1);}
else { return bsearch(nums1, nums2); }
}
};