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);
}
}