演算法思路:每次取兩個數組的中位元進行比較,
我們假定取的中位元是下中位元,即每次取中位元座標時使用floor取出,當數組長度是奇數時,取得是正中間的元素,是偶數時取得就是下中位元
1. a[n/2] == b[n/2],可知中位元即為a[n/2],返回即可
2. a[n/2] < b[n/2],設a,b數組藍色紅色部分元素分別為a[b],a[r],b[b],b[r],
可知 a[b] <= a[n/2] < b[n/2] <= b[b]
於是有 a[b] <= a[r], a[b] < b[b] (數組元素可能存在重複)
b[b] >= b[r] , b[b] > a[b]
這樣我們就知道了a[b]中的元素至少小於n個元素,b[b]中的元素至少大於n個元素,易知中位元就不可能在藍色部分了
那麼排除了藍色部分以後,就可以對紅色部分重新用取中位元的方法來尋找總的中位元,直到切分後的數組只剩一個元素,我們取較小的那個元素即可
那麼在從中位元座標切分數組時,我們到底要不要把中位元元素也放入紅色部分呢?這裡有兩種情況
1)當n為奇數時,我們需要把a,b的中位元都放入紅色部分進行遞迴尋找,因為當a,b數組合并後,a[n/2] b[n/2]仍然有可能排在合并數組的正中間,那麼中位元就是二者其一
舉個例子, a = (1,3,5,7,9), b = (2,4,6,8,10),最後拍出來肯定是1,2,3,4,5,6,7,8,9,10,可見這裡5,6都是中位元
2)當n為偶數時,我們需要將較小的那個中位元排除掉,只讓他右邊的紅色部分進入遞迴尋找(這裡是排除a[n/2],如果a[n/2] > b[n/2],則排除b[n/2])
這是因為如果數組長度是偶數,那麼我們取的中位元肯定是下中位元,且a[n/2] < b[n/2],則數組合并以後a[n/2]肯定位於總中位元的左邊,所以a[n/2]肯定不是最後的中位元
舉個例子, a = (1,3,5,7), b = (2,4,6,8),則最後排出來是12345678,我們取的中位元是3, 4,可見3不可能是中位元,中位元是4,5
好了。下面看代碼
1 <?php 2 #兩個長度皆為n的數組,兩個數組已排序,求兩個數組所有數字中的中位元 3 function get_mid($a, $b) { 4 print_r($a); 5 echo "<br>"; 6 print_r($b); 7 echo "<br>"; 8 if (count($a) == 1) { 9 $result_mid = min($a[0], $b[0]); #如果數組只剩一個元素,返回這個元素即為中位元10 } else {11 $mid = floor((count($a) - 1) / 2); #中位元座標取下中位元12 echo "mid : {$mid}<br>";13 14 #如果a[mid] == b[mid],則中位元就是mida,返回即可15 #如果a[mid] < b[mid],選擇數組a的右部,數組b的左部進入遞迴,直到最後遞迴部分數組長度為116 #如果a[mid] > b[mid],選擇數組a的左部,數組b的右部進入遞迴,直到最後遞迴部分數組長度為117 18 #此處需要特別注意,當數組長度為奇數時,切分AB數組都要把中位元加上19 #但數組長度為偶數時,只需要把較大的數組的左部加上中位元,較小的數組則捨棄中位元只要右部進入遞迴20 21 if (count($a) % 2 == 0) {22 $small_arr_start = $mid + 1;23 } else {24 $small_arr_start = $mid;25 }26 27 if ($a[$mid] == $b[$mid]) { #兩數組中位元相等,返回中位元28 $result_mid = $a[$mid];29 } else if ($a[$mid] < $b[$mid]) { #此處需要特別注意30 $atemp = array_slice($a, $small_arr_start); #切分數組,較小的數組根據長度是否是奇偶捨棄中位元31 $btemp = array_slice($b, 0, $mid + 1);32 $result_mid = get_mid($atemp, $btemp);33 } else {34 $atemp = array_slice($a, 0, $mid + 1);35 $btemp = array_slice($b, $small_arr_start);36 $result_mid = get_mid($atemp, $btemp);37 }38 }39 40 return $result_mid;41 }42 43 $a = array(1, 3, 5, 5, 7, 8, 9);44 $b = array(2, 2, 7, 8, 9, 10, 14);45 46 echo "midnum : " . get_mid($a, $b) . "<br>";47 48 array_splice($a, count($a) - 1, 0, $b);49 sort($a);50 51 print_r($a);52 ?>
Array ( [0] => 1 [1] => 3 [2] => 5 [3] => 5 [4] => 7 [5] => 8 [6] => 9 )
Array ( [0] => 2 [1] => 2 [2] => 7 [3] => 8 [4] => 9 [5] => 10 [6] => 14 )
mid : 3
Array ( [0] => 5 [1] => 7 [2] => 8 [3] => 9 )
Array ( [0] => 2 [1] => 2 [2] => 7 [3] => 8 )
mid : 1
Array ( [0] => 5 [1] => 7 )
Array ( [0] => 7 [1] => 8 )
mid : 0
Array ( [0] => 7 )
Array ( [0] => 7 )
midnum : 7
Array ( [0] => 1 [1] => 2 [2] => 2 [3] => 3 [4] => 5 [5] => 5 [6] => 7 [7] => 7 [8] => 8 [9] => 8 [10] => 9 [11] => 9 [12] => 10 [13] => 14 )