題目描述:
給定兩個大小爲 m 和 n 的有序數組 nums1 和 nums2。
請你找出這兩個有序數組的中位數,並且要求算法的時間複雜度爲 O(log(m + n))。
你可以假設 nums1 和 nums2 不會同時爲空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
則中位數是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
則中位數是 (2 + 3)/2 = 2.5
反思錯誤:
①二分 做的話,各種需要注意腳標的地方……超級混亂,最後除二 指向的哪裏都不知道了。
解題思路:
一、先說說二分的思路吧:(官方題解 說是遞歸法,我覺得說二分更妥當)
既然是找中位數,那麼首先明確 中位數 左邊的數 的個數 一定等於 右邊的數 的個數 。
好,這樣的話,我們只需要關注最短的數組就可以了,,,爲什麼?看下邊。
當我們取 短數組的 i 位置時,要保證中位數左右個數相等,那麼長數組 必定 要取 (nums1.length + nums.length) / 2 - i 位置【我這裏只是爲了方便理解,這麼寫的,事實不一定】,,,
而且先取短數組 的好處 在於 長數組就可定不會 越界!!【因爲長數組的長度一定大於一半】
然後就是對短數組 進行 二分,比較,再分………………不想說了,二分我覺得太亂。
二、說說下邊這個方法:(我覺得特好理解)
同樣的,中位數 左右兩邊的 個數 相等。
那先建一個數組 res 長度爲 總長一半 加一;
剩下的就簡單了;;;循環唄,看nums1小 還是 nums2 小,誰小,,數組res就把誰放進去
那麼最後 總和奇數個 返回res[總長一半]
總數偶數個 返回 ( res[總長一半 - 1] + res[總長一半] )/ 2.0
Java代碼(二分):
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 = 0;
if (i == 0) { maxLeft = B[j-1]; }
else if (j == 0) { maxLeft = A[i-1]; }
else { maxLeft = Math.max(A[i-1], B[j-1]); }
if ( (m + n) % 2 == 1 ) { return maxLeft; }
int minRight = 0;
if (i == m) { minRight = B[j]; }
else if (j == n) { minRight = A[i]; }
else { minRight = Math.min(B[j], A[i]); }
return (maxLeft + minRight) / 2.0;
}
}
return 0.0;
}
}
Java代碼(雙指針):
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
int lenhalf = (len1+len2)/2;
boolean isOdd = (len1+len2)%2 != 0;
return search(nums1,nums2,lenhalf,isOdd);
}
double search(int[] nums1,int[] nums2,int lenhalf,boolean isOdd){
int[] res = new int[lenhalf+1];
int indexPoint1 = 0,len1 = nums1.length;
int indexPoint2 = 0,len2 = nums2.length;
for(int i=0;i<=lenhalf;++i){
if(indexPoint2==len2 || (indexPoint1<len1 && nums1[indexPoint1]<nums2[indexPoint2]))
res[i] = nums1[indexPoint1++];
else if(indexPoint2<len2)
res[i] = nums2[indexPoint2++];
}
if(isOdd)
return res[lenhalf];
else
return (res[lenhalf-1]+res[lenhalf])/2.0;
}
}