其中,N1=4,N2=6,size=4+6=10.
1,現在有的是兩個已經排好序的數組,結果是要找出這兩個數組中間的數值,如果兩個數組的元素個數為偶數,則輸出的是中間兩個元素的平均值。
2,可以想象,如果將數組1隨便切一刀(如在3和5之間切一刀),數組1將分成兩份,數組1左別的元素的個數為1,右邊的元素的個數為3。
由於數組1和數組2最終分成的左右兩份的個數是確定的,都是所有元素的個數的一半(size/2=5)所以我們也可以知道,此時對數組2應該切的一刀的位置應該在10和11之間,數組2左邊的個數為4,右邊的個數為2.才能使兩個數組左右兩邊的元素個數加起來的和(1+4=2+3)相等。
另外,我們記在數組1靠近這一刀的左別的元素為L1(3),右邊元素為R1(5).同理,記在數組2靠近這一刀的左別的元素為L2(10),右邊元素為R2(11).
如果這一刀的位置是正確的,則應該有的結果是
L1<=R2
L2<=R1
這樣就能確保,左邊的元素都小於右邊的元素了。
3,所以,我們只需要直接找出在數組1切這一刀的正確位置就可以了。
為了減少查找次數,我們對短的數組進行二分查找。將在數組1切割的位置記為cut1,在數組2切割的位置記為cut2,cut2=(size/2)-cut1。
cut1,cut2分別表示的是數組1,數組2左邊的元素的個數。
4,切這一刀的結果有三種
1)L1>R2 則cut1應該向左移,才能使數組1較多的數被分配到右邊。
2)L2>R1 則cut1應該向右移,才能使數組1較多的數被分配到左邊。
3)其他情況(L1<=R2 L2<=R1),cut1的位置是正確的,可以停止查找,輸出結果。
5,其他說明
1)考慮到邊界條件,就是cut的位置可能在邊緣,就是cut1=0或者cut1=N1,cut2=0或者cut2=N2的這些情況,我們將min和max兩個特殊值分別加在數組1和數組2的兩端,就可以統一考慮了。還有N1個數為0的時候,直接輸出結果即可。
2)為了減少查找時間,使用的是二分查找,就是cut1的位置是一半一半的查找的,實現時間只要log(N),不然就會超時。所以,我們不能只是簡單地將cut1–或者cut1++,而是要記下每次cut1的區域范圍,我們將cut1的范圍記錄下來,用[cutL,cutR]表示。一開始cut1的范圍是[cutL,cutR]=[0,N1],
如果L1>R2 則cut1應該向左移,才能使數組1較多的數被分配到右邊。cut1的范圍就變成了[cutL,cut1-1],下次的cut1的位置就是cut1 = (cutR - cutL) / 2 + cutL;。
如果L2>R1 則cut1應該向右移,才能使數組1較多的數被分配到左邊。cut1的范圍就變成了[cut1+1,cutR],下次的cut1的位置就是cut1 = (cutR - cutL) / 2 + cutL;。
3)數組的元素個數和是奇數的情況下,中間的元素應該就是min(R1,R2),只需另外處理輸出就可以了。
time log(min(m,n))
space o(1)
1 class Solution { 2 public static double findMedianSortedArrays(int[] nums1, int[] nums2) { 3 if(nums1.length > nums2.length){ 4 return findMedianSortedArrays(nums2, nums1); 5 } 6 int len = nums1.length + nums2.length; 7 int cut1 = 0; 8 int cut2 = 0; 9 int cutL = 0; 10 int cutR = nums1.length; 11 while(cut1 <= nums1.length){ 12 cut1 = (cutR - cutL)/2 + cutL; 13 cut2 = len/2 - cut1; 14 double L1 = (cut1 == 0 )? Integer.MIN_VALUE:nums1[cut1 - 1]; 15 double L2 = (cut2 == 0 )? Integer.MIN_VALUE:nums2[cut2 - 1]; 16 double R1 = (cut1 == nums1.length )? Integer.MAX_VALUE:nums1[cut1]; 17 double R2 = (cut2 == nums2.length )? Integer.MAX_VALUE:nums2[cut2]; 18 if(L1>R2){ 19 cutR = cut1 - 1; 20 }else if(L2 > R1){ 21 cutL = cut1 + 1; 22 }else{ 23 if(len %2 == 0){ 24 L1 = (L1 > L2) ? L1 : L2; 25 R1 = (R1 > R2 )? R2 : R1; 26 return (L1+R1)/2; 27 }else{ 28 R1 = (R1 < R2) ? R1 : R2; 29 return R1; 30 } 31 } 32 } 33 return -1; 34 } 35 36 }
轉自https://blog.csdn.net/chen_xinjia/article/details/69258706
2019-03-11 23:06:05