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)).
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
解法一:
To solve this problem, we need to understand "What is the use of median". In statistics, the median is used for dividing a set into two equal length subsets, that one subset is always greater than the other
. If we understand the use of median for dividing, we are very close to the answer.
First let's cut A into two parts at a random position i:
left_A | right_A
A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1]
Since A has m elements, so there are m+1 kinds of cutting( i = 0 ~ m ). And we know: len(left_A) = i, len(right_A) = m - i . Note: when i = 0 , left_A is empty, and when i = m , right_A is empty.
With the same way, cut B into two parts at a random position j:
left_B | right_B
B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]
Put left_A and left_B into one set, and put right_A and right_B into another set. Let's name them left_part and right_part :
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]
If we can ensure:
1) len(left_part) == len(right_part)
2) max(left_part) <= min(right_part)
then we divide all elements in {A, B} into two parts with equal length, and one part is always greater than the other. Then median = (max(left_part) + min(right_part))/2.
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size(), n = nums2.size();
if(n < m) return findMedianSortedArrays(nums2, nums1);
int i, j, imin = 0, imax = m;
while(imin <= imax){// 注意 是小于或等于
i = (imin + imax) / 2;
j = (m + n + 1) / 2 - i;
if(j < n && i > 0 && nums1[i - 1] > nums2[j]) imax = i - 1;// 注意 +1 -1 二分法
else if(j > 0 && i < m && nums2[j - 1] > nums1[i]) imin = i + 1;
else break;
}
int R1;
if(i == 0) R1 = nums2[j - 1];// 对于这种边界的一定要加以判断
else if(j == 0) R1 = nums1[i - 1];
else R1 = max(nums1[i - 1], nums2[j - 1]);
if((n + m) % 2) return R1;// 注意 如果m + n 是奇数的话 只用R1即可。
int R2;
if(i == m) R2 = nums2[j];
else if(j == n) R2 = nums1[i];
else R2 = min(nums1[i], nums2[j]);
return (R1 + R2) / 2.0;
}
方法2:
We have two arrays:
nums1[0], nums1[1]....nums1[m - 1];
nums2[0], nums2[2]....nums2[n - 1];
the result after merging:
num[0],num[1],num[2]...num[m + n - 1];
Let‘s compare nums1[k / 2 - 1]
and nums2[k / 2 - 1]
if nums1[k / 2 - 1] < nums2 [k / 2 - 1]
then the nums1[k / 2 - 1]
and it's left side elements
must smaller than k
th number in num arrary(num[k - 1]
).
class Solution {
public:
int kth(int a[], int m, int b[], int n, int k) {
if (m < n) return kth(b,n,a,m,k);
if (n==0) return a[k-1];
if (k==1) return min(a[0],b[0]);
int j = min(n,k/2);
int i = k-j;
if (a[i-1] > b[j-1]) return kth(a,i,b+j,n-j,k-j);
return kth(a+i,m-i,b,j,k-i);
}
double findMedianSortedArrays(int a[], int m, int b[], int n) {
int k = (m+n)/2;
int m1 = kth(a,m,b,n,k+1);
if ((m+n)%2==0) {
int m2 = kth(a,m,b,n,k);
return ((double)m1+m2)/2.0;
}
return m1;
}
};