給定兩個大小爲 m 和 n 的有序數組 nums1 和 nums2算法
你能夠假設 nums1 和 nums2 不會同時爲空。數組
示例 1:動畫
nums1 = [1, 3]nums2 = [2]spa
則中位數是 2.03d
示例 2:code
nums1 = [1, 2]nums2 = [3, 4]視頻
則中位數是 (2 + 3)/2 = 2.5blog
兩個有序數組,合併成一個有序數組,取中位數,
思路很清晰leetcode
這裏只要取中位數,只要保證,這個數字左邊的元素個數( 數組一左邊 i 個+數組二左邊 j 個 )與右邊的元素個數相等,這個數字左邊的元素都小於右邊的元素,rem
就能夠認爲,這個數字是咱們想要的
由於是中間位置的數字,
若是第一個數組 nums1 取 i 個,( 0 <= i <= m ),
那麼第二個數組 nums2 裏面取 j 個, ( 0 <= j <= n ),
i 與 j 知足必定的關係 i + j = ( m + n )/2
, 或者 i + j = ( m + n + 1)/2
, 由於 m + n 多是奇數,也多是偶數。
那麼 j = ( m + n + 1 ) / 2 - i
i 和 j 把兩個數組,各分紅兩片,出現了四個關鍵的數字,
數組一左邊最大,num1LeftMax
數組一右邊最小,num1RightMin
數組二左邊最大,num2LeftMax
數組二右邊最小,num2RightMin
若是 num1LeftMax <= num2RightMin, num2LeftMax <= num1RightMin, 就找到咱們想要的中位數了,由於 num1 是有序數組,num1LeftMax 固然小於 num1RightMin,一樣的 num2LeftMax < num2RightMin
爲何是 O(m), 由於這就是二分搜索。
通常咱們的二分搜索是一個有序數組,查找元素,每一次查找,把搜索範圍縮減一半。經過移動上邊界和下邊界
就是比較條件相對簡單,直接比元素大小
這道題其餘與基礎的二分查找一致, 比較條件有些變化
若是 num1LeftMax > num2RightMin, 數字一左邊的大了,就是 i 大了,就要移動右邊界,就是右邊界變小
(左邊界只能右移,只能變大。右邊界只能左移,只能變小)
其餘狀況,相似處理
示例 3:
nums1 = [ 1, 3,8,9,15 ]nums2 = [ 7, 11, 18, 19, 21,25 ]
中位數是 11
左邊有 5 個元素, m = 5,
右邊有 6 個, n = 6
數組一右邊最小,num1RightMin < 數組二左邊最大,num2LeftMax
就是 i 小了,左邊界右移, low = 3
如今知足要求了,m + n 是奇數,左邊多一個,選數組一左邊最大和數組二左邊最大中較大的,就是 11
示例 4:
nums1 = [ 23, 26,31,35 ]nums2 = [ 3, 5, 7, 9, 11,16 ]
中位數是 13.5, 11 和 16 的平均值
左邊有 4 個元素, m = 4,
右邊有 6 個, n = 6
數組一左邊最大,num1LeftMax > 數組二右邊最小,num2RightMin
就是 i 大了,右邊界左移, high = 1
左邊一個元素都不要,默認數組一左邊最大爲負無窮,num1LeftMax = Number.MIN_SAFE_INTEGER
,
如今知足要求了,m + n 是偶數,找出中間兩個 11 與 16,求平均值爲 13.5
PS: 我的看,看書和看算法動畫,不錯,就是少了一點參與感。
拿起鋼筆,寫寫畫畫,須要保證結果一致嘛,我感受,理解的好一些
選短的數組處理,處理快,還保證了 j 必定大於 0 (由於 n > m),避免了一些邏輯處理。
裏面處理了一些邊界條件, i = 0, 第一個數組左邊一個元素都不要,i = m, 第一個數組右邊一個元素都不要
m + n 的值是奇數,這個好處理一點,只須要找出一個元素
m + n 的值是偶數,須要找出兩個元素
var findMedianSortedArrays = function (nums1, nums2) { if (nums1.length > nums2.length) { [nums1, nums2] = [nums2, nums1] } const arr1Length = nums1.length, arr2Length = nums2.length; let low = 0, high = arr1Length; const halfLen = Math.floor((arr1Length + arr2Length + 1) / 2); while (low <= high) { let i = Math.floor((low + high) / 2); let j = halfLen - i; let num1LeftMax = i == 0 ? Number.MIN_SAFE_INTEGER : nums1[i - 1] let num1RightMin = i == arr1Length ? Number.MAX_SAFE_INTEGER : nums1[i] let num2LeftMax = j == 0 ? Number.MIN_SAFE_INTEGER : nums2[j - 1] let num2RightMin = j == arr2Length ? Number.MAX_SAFE_INTEGER : nums2[j] if (num1LeftMax <= num2RightMin && num2LeftMax <= num1RightMin) { var answer = 0 if (Math.round((arr1Length + arr2Length) % 2) == 1) { answer = Math.max(num1LeftMax, num2LeftMax) } else { // Math.round((arr1Length + arr2Length) % 2) == 0 let leftMax = Math.max(num1LeftMax, num2LeftMax) let rightMin = Math.min(num1RightMin, num2RightMin) answer = (leftMax + rightMin) / 2 } return answer } else if (num1LeftMax > num2RightMin) { high = i - 1 } else { // num2LeftMax > num1RightMin low = i + 1 } } return 0; };
我還喜歡看視頻,有一個 youtube ,連接是 https://www.youtube.com/watch... .本文能夠做爲該視頻和 Leatcode 官方題解的補充, 官方題解: https://leetcode.com/problems...