There are two sorted arrays A and B 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)).
分析:
看见对数时间复杂度,那么一定是二分查找,关键怎么找这个分割点。
这个题,变成寻找A,B中第k大的数(k从0开始),每次按A,B长度比例将k分配到A,B数组中,
即
aMidLen = k*aLen/(aLen + bLen)
bMidLen = k - aMidLen -1
aMid = aStart + aMidLen //a分割点
bMid = bStart + aMidLen //b分割点
因为包括两分割点前面有k个元素,
则:
如果A[aMid] > B[bMid], 说明 B中bMid(包括bMid)前面的元素一定在k个之内,且 A中aMid之后的元素一定在k个之外了,可以舍去这两部分,同时k要减去B前面的个数;
反之,同理。
按照以上方式,递归二分。
递归终结条件是:
1,有一个数组长度为0,那么就是另一个数组中第k个数;
2,k变成0,那么就是两数组开头较小的那个。
另外,
对于奇数个元素的有序数组,中位数就是中间那一个,
对于偶数个元素的有序数组,中位数是中间两个的平均。
public class Solution {
public double findMedianSortedArrays(int A[], int B[]) {
int m = A.length;
int n = B.length;
if((m+n)%2 != 0)//奇数,为中间一个
return (double) findKth(A, B, (m+n)/2, 0, m-1, 0, n-1);
else//偶数,为中间两个的平均
return 0.5*(findKth(A, B, (m+n)/2, 0, m-1, 0, n-1) + findKth(A, B, (m+n)/2-1, 0, m-1, 0, n-1));
}
//A,B中第k大的数,k从0开始数
public int findKth(int A[], int B[], int k, int aStart, int aEnd, int bStart, int bEnd){
int aLen = aEnd-aStart+1;
int bLen = bEnd-bStart+1;
if(aLen == 0)
return B[bStart+k];
if(bLen == 0)
return A[aStart+k];
if(k == 0)
return Math.min(A[aStart], B[bStart]);
//按比例将k分成两部分,按比例分配避免等分的数组越界问题
int aMidLen = k*aLen/(aLen+bLen);
int bMidLen = k-aMidLen-1;
int aMid = aMidLen + aStart;
int bMid = bMidLen + bStart;
if(A[aMid] > B[bMid]){
//舍弃A的后半部分,B的前半部分,k减小B前半部分长度
k = k - (bMid-bStart+1);
aEnd = aMid;
bStart = bMid+1;
}else{
//舍弃A的前半部分,B的后半部分,k减小A前半部分长度
k = k - (aMid-aStart+1);
bEnd = bMid;
aStart = aMid+1;
}
return findKth(A, B, k, aStart, aEnd, bStart, bEnd);
}
}