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)).
提到log(m),自然会想到二分查找。
本题相比一个数组寻找指定元素的索引,是对对两个有序数组寻找他们的中间值,一开始我考虑的是将两个数组元素逐个比较放入一个数组,再寻找中间值,这样耗时0(m+n),不符合我们的要求。
我们可以设想本题中的两个数组是由一个数组一分为2,那么核心问题:
在1个数组中运用二分查找比较容易,如何在两个数组中联合起来运用二分查找?
由这个核心问题,我们可以提取几个元素:
1.分别切割两个数组,我们必须确保分别相加两个数组左边和右边,元素个数相等或者相差为1.
即:i + j = (m - i) + (n - j) + 1;(这里的1确保了左边等于右边元素个数或者比右边元素个数多1)
2.切割后,如果满足A[i -1] <= B[j] ,B[i -1] <= A[j], 才是找对了切割点,不然要继续进行二分查找,进行切割。
/** cost 70ms
* pass 2080 cases
*/
public static double findMedianSortedArrays1(int[] nums1,int[] nums2){
int m = nums1.length;
int n = nums2.length;
if(m > n){
return findMedianSortedArrays1(nums2, nums1);
}
if(m == 0)
return ((double)nums2[(n-1)/2] + (double)nums2[n/2])/2;
int imin = 0;
int imax = m;
int half_len = (m + n + 1)/2; //如果是奇数,左边会多一个数
int max_of_left = 0;
int min_of_right = 0;
int i = 0,j = 0;
while(imin <= imax){
i = (imin + imax)/2;
j = half_len - i;
if(i < m && nums2[j-1]>nums1[i])
imin = i + 1;
else if(i > 0 && nums1[i-1]>nums2[j])
imax = i - 1;
else
break;
}
if(i == 0){
max_of_left = nums2[j-1];
}
else if(j == 0){
max_of_left = nums1[i-1];
}
else{
max_of_left = Math.max(nums1[i-1],nums2[j-1]);
}
if((m+n)%2 == 1)
return max_of_left;
else if(i == m)
min_of_right = nums2[j];
else if(j == n)
min_of_right = nums1[i];
else
min_of_right = Math.min(nums1[i],nums2[j]);
return (double)(max_of_left + min_of_right) / 2;
}