首先擺上題目:數組
剛開始,看到時間複雜度爲O(log(m+n)),立馬就會想到二分法,沒錯,可是針對這一題而言,拿到的是兩個數組,兩個數組長度的和爲奇數和偶數怎麼處理?遇到什麼狀況進行二分?怎麼分?這是咱們必須考慮的問題。函數
首先,鞏固一下中位數的概念: 有n個已經排好序的數。ui
對於n爲奇數的狀況,中位數則是第(n+1)/2個,即最中間的那個數。spa
對於n爲偶數的狀況,中位數則是第n/2個數和第n/2 + 1個數的算術平均值。code
設總長度爲n,找到第(n+1)/2個數,再找到第(n+2)/2個數 (注意:索引值都向下取整)。 而後,求兩個數的平均值,便是最後要求的中位數。這樣能夠涵蓋奇數和偶數的任一狀況。cdn
回到原題的起點,咱們是要找到特定位置的數,那麼想想能夠經過什麼方式排除絕對不屬於這個位置的數?blog
好比如今兩個數組是[1, 2, 4, 6, 8], [5, 7, 9,11]。總長度爲9,中位數爲第5個,一個數組還好辦,不過如今是兩個數組的狀況,咱們採起一個比較巧妙的方式得到第5個數:索引
step1: 將5/2, 向下取整即爲2,比較兩個數組的第二個數,對應爲2和7,明顯前者比後者小,那麼如今直接把第一個數組的前2個數剔除,由於它們百分之百在中位數的前面。it
step2: 那麼,如今咱們肯定了前2個數,那即將要求的就是後面全部的數字中排第3的數了。按照以前的作法,3/2,向下取整爲1, 比較兩個數組的第一個數,對應4和5, 前者比後者小,直接把第一個數組的前1個數剔除,由於百分之百在中位數的前面,不用考慮。io
step3: OK,如今咱們肯定了前三個數,即將要求的就是後面全部的數字中排第2的數了,依照上述作法,咱們剔除了5。
step4: 如今肯定了前四個數,即將要求的就是後面全部的數字中第1個數了,直接比較目前兩個數組的第一個數便可,6 < 7, 咱們取6。完成!
將問題通常化就是獲取第k個數,取兩個數組中第k/2個數進行比較,若是比較小,就把這個數組的前k/2個元素所有剔除,依次循環,直到k爲1或者有一個數組爲空。
這種狀況,咱們只須要取這個數組末尾的元素便可。
代碼以下:
//找到第k大的元素
const findKMax = (num1, start1, end1, num2, start2, end2, k) => {
let len1 = end1 - start1 + 1;
let len2 = end2 - start2 + 1;
//這裏我是來保證num1的長度必定小於num2,這樣肯定num1爲空,直接來取num2的第k個數
if (len1 > len2)
return findKMax(num2, start2, end2, num1, start1, end1, k);
if (len1 == 0) return num2[start2 + k - 1];
if (k == 1) return Math.min(num1[start1], num2[start2]);
// |0這個操做爲向下取整
//若是k/2比其中一個數組的長度還要大,取數組末尾元素便可
let i = start1 + Math.min(len1, k / 2 | 0) - 1;
let j = start2 + Math.min(len2, k / 2 | 0) - 1;
if (num1[i] > num2[j])
//已經剔除j - start2 + 1個元素
return findKMax(num1, start1, end1, num2, j + 1, end2, k - (j - start2 + 1));
else
//已經剔除i - start1 + 1個元素
return findKMax(num1, i + 1, end1, num2, start2, end2, k - (i - start1 + 1));
}
//核心函數
const findMedianSortedArrays = (nums1, nums2) => {
let m = nums1.length;
let n = nums2.length;
//向下取整
let left = (m + n + 1) / 2 | 0;
let right = (m + n + 2) / 2 | 0;
//處理了數組總長度爲奇數和偶數的狀況
return (findKMax(nums1, 0, nums1.length - 1, nums2, 0, nums2.length - 1, left) +
findKMax(nums1, 0, nums1.length - 1, nums2, 0, nums2.length - 1, right)) * 0.5;
}
複製代碼
成功AC!