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
这个题目要求运行时间复杂度必须是O(log(m+n)) ,所以要充分利用数组是已经排好序的特性。
网上有很多关于这个问题的分析,把这个问题转化为从两个排好序的数组中求第K 大的数。 具体思想,就是先以 K/2 为基准,看看 K/2 这些数是落在那个数组中,在循环/递归查找剩下的数。
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int len = nums1.size() + nums2.size();
if(len %2 == 1) {
return findKth(&nums1[0], nums1.size(), &nums2[0], nums2.size(), len /2 + 1) ;
} else {
return (findKth(&nums1[0], nums1.size(), &nums2[0], nums2.size(), len /2)
+ findKth(&nums1[0], nums1.size(), &nums2[0], nums2.size(), len /2 + 1) ) / 2.0;
}
}
函数 findKth 的非递归实现如下:
int findKth(int a[], int la, int b[], int lb, int k) {
assert( la + lb >= k);
int m, n;
while(1) {
if( la == 0 ) return b[k-1];
if( lb == 0 ) return a[k-1];
if( k == 1) return a[0] > b[0] ? b[0] : a[0] ;
if( la + lb == k ) return a[0] > b[0] ? a[la-1] : b[lb-1] ;
m = la > k/2 ? k/2 : la;
n = lb > k - m ? k - m : lb ;
if( m + n != k) {
n = lb > k/2 ? k/2 : lb;
m = k - n;
}
if(a[m-1] < b[n-1]) {
a += m ;
la -= m;
k-= m ;
} else if ( b[n-1] < a[m-1]) {
b += n ;
lb -= n;
k -= n;
} else {
return a[m - 1] ;
}
}
}
对于求第K 大的数,网上很多都是采用了递归的方法来实现,实现的代码:
int findKth(int a[], int m, int b[], int n, int k) {
if( m == 0 ) return b[k-1];
if( n == 0 ) return a[k-1];
if(k == 1) return a[0] > b[0] ? b[0] : a[0] ;
if( k == m + n) return a[m-1] > b[n-1] ? a[m-1] : b[n-1];
if( m > n ) return findKth(b, n, a, m, k); //make sure m < n
int la = m > k/2 ? k/2 : m;
int lb = k - la;
if(a[la-1] < b[lb-1] ) return findKth(a + la, m -la, b, n, k - la);
else if( a[la-1] > b[lb-1]) return findKth(a, m, b + lb, n - lb, k -lb);
else return a[la-1];
}