官方題解:
/*
* 1.首先,讓我們在任一位置 i 將 A(長度爲m) 劃分成兩個部分:
* leftA | rightA
* A[0],A[1],... A[i-1] | A[i],A[i+1],...A[m - 1]
*
* 由於A有m個元素,所以有m + 1種劃分方式(i = 0 ~ m)
* 以上得出 leftA.length = i; reghtA.length = m - i
* 注意:當i = 0時,leftA是空集,而當i = m時,rightA爲空集。
*
* 2.採用同樣的方式,將B也劃分爲兩部分:
* leftB | rightB
* B[0],B[1],... B[j-1] | B[j],B[j+1],...B[n - 1]
* 以上得出 leftB.length = j; reghtB.length = n - j
*
* 將leftA和leftB合併爲leftPart,將rightA和rightB合併爲rightPart。
*
* leftPart | rightPart
* A[0],A[1],... A[i-1] | A[i],A[i+1],...A[m - 1]
* B[0],B[1],... B[j-1] | B[j],B[j+1],...B[n - 1]
*
* 如果我們可以確認:
* 1.len(leftPart) = len(rightPart); =====> 該條件在m+n爲奇數時,該推理不成立
* 2.max(leftPart) <= min(rightPart);
*
* median = (max(leftPart) + min(rightPart)) / 2; 目標結果
*
* 要確保這兩個條件滿足:
* 1.i + j = m - i + n - j(或m - i + n - j + 1) 如果n >= m。只需要使i = 0 ~ m,j = (m+n+1)/2-i =====> 該條件在m+n爲奇數/偶數時,該推理都成立
* 2.B[j] >= A[i-1] 並且 A[i] >= B[j-1]
*
* 注意:
* 1.臨界條件:i=0,j=0,i=m,j=n。需要考慮
* 2.爲什麼n >= m ? 由於0 <= i <= m且j = (m+n+1)/2-i,必須確保j不能爲負數。
*
* 按照以下步驟進行二叉樹搜索
* 1.設imin = 0,imax = m,然後開始在[imin,imax]中進行搜索
* 2.令i = (imin+imax) / 2, j = (m+n+1)/2-i
* 3.現在我們有len(leftPart) = len(rightPart)。而我們只會遇到三種情況:
*
* ①.B[j] >= A[i-1] 並且 A[i] >= B[j-1] 滿足條件
* ②.B[j-1] > A[i]。此時應該把i增大。 即imin = i + 1;
* ③.A[i-1] > B[j]。此時應該把i減小。 即imax = i - 1;
*
* */
class Solution {
public double findMedianSortedArrays(int[] A, int[] B) {
int m = A.length;
int n = B.length;
if (m > n) { // to ensure m<=n
int[] temp = A; A = B; B = temp;
int tmp = m; m = n; n = tmp;
}
int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
while (iMin <= iMax) {
int i = (iMin + iMax) / 2;
int j = halfLen - i;
if (i < iMax && B[j - 1] > A[i]) {
iMin = i + 1; // i is too small
} else if (i > iMin && A[i - 1] > B[j]) {
iMax = i - 1; // i is too big
} else { // i is perfect
int maxLeft;
//A分成的leftA(空集) 和 rightA(A的全部) 所以leftPart = leftA(空集) + leftB,故maxLeft = B[j-1]。
if (i == 0) {
maxLeft = B[j - 1];
//B分成的leftB(空集) 和 rightB(B的全部) 所以leftPart = leftA + leftB(空集),故maxLeft = A[i-1]。
} else if (j == 0) {
maxLeft = A[i - 1];
//排除上述兩種特殊情況,正常比較
} else {
maxLeft = Math.max(A[i - 1], B[j - 1]);
}
//奇數,中位數正好是maxLeft
if ((m + n) % 2 == 1) {
return maxLeft;
}
//偶數
int minRight;
//A分成的leftA(A的全部) 和 rightA(空集) 所以rightPart = rightA(空集) + rightB,故minRight = B[j]。
if (i == m) {
minRight = B[j];
//B分成的leftB(B的全部) 和 rightB(空集) 所以rightPart = rightA + rightB(空集),故minRight = A[i]。
} else if (j == n) {
minRight = A[i];
//排除上述兩種特殊情況,正常比較
} else {
minRight = Math.min(B[j], A[i]);
}
return (maxLeft + minRight) / 2.0;
}
}
return 0.0;
}
}
執行用時:2 ms
內存消耗:41.8 MB