第四题是求两个有序数组的中位数,比如nums1[1]=[1,2], nums2=[3,4], 那么中位数是2.5。
这道题的时间复杂度要求log(m+n),可以用二分查找。
如何在两个数组上进行二分查找?
在较短的那个数组上[l,r]区间查找,比较nums1[i-1]和nums2[j],nums1[i]和nums2[j-1]的关系。
如果nums1[i]>=nums2[j-1], nums1[i-1]<=nums2[j], 则说明i的位置合适。如果m+n奇数,中位数为max(nums1[i-1],nums2[j-1]),否则中位数为(max(nums1[i-1],nums2[j-1])+min(nums1[i],nums2[j]))/2。注意检查边界。
如果nums1[i]<nums2[j-1],说明i小了,需要将搜索区域的左端右移(l++)。
如果nums1[i-1]>nums2[j],说明j大了,需要将搜索区域的右端左移(r--)。
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
if ( m > n ) {
int[] nums3 = nums1;
nums1 = nums2;
nums2 = nums3;
int k = m;
m = n;
n = k;
}
int l = 0;
int r = m;
int half = ( m + n + 1 ) / 2;
while ( l <= r ){
int i = ( l + r ) / 2;
int j = half - i;
if (i < m && nums1[i] < nums2[j-1]){ //i small
l = l + 1;
}
else if (i > 0 && nums1[i-1] > nums2[j]){ //i big
r = r - 1;
}
else{ //i ok
int ll = 0;
if (i == 0) {
ll = nums2[j-1];
}else if (j == 0) {
ll = nums1[i-1];
}else if (nums1[i-1] > nums2[j-1]){
ll=nums1[i-1];
}else ll=nums2[j-1];
if ((m + n) % 2 == 1) return ll;
int rr = 0;
if (i == m) {
rr = nums2[j];
}else if (j == n) {
rr = nums1[i];
}else if (nums1[i] < nums2[j]){
rr=nums1[i];
}else rr=nums2[j];
return (ll + rr)/2.0;
}
}
return 0.0;
}
}