[4] 尋找兩個正序數(shù)組的中位數(shù)

鏈接:尋找兩個正序數(shù)組的中位數(shù)

兩個遞增數(shù)組找中位數(shù),最終結(jié)果一定是础钠,通過兩條線分別劃分兩個數(shù)組抒抬,使得兩個左半數(shù)組的元素個數(shù)之和與兩個右半數(shù)組元素之和相等或者大1(即總數(shù)為奇數(shù)時,將中位數(shù)放到左邊)炬藤。

只要給定兩個數(shù)組的長度m和n,左邊的元素個數(shù)時確定的豪嚎,左邊的元素個數(shù)left\_size=\frac{m+n+1}{2}细卧,這里的除法為計算機整除,向下取整郊闯。

當m+n為奇數(shù)時妻献,比如2+3,left\_size=\frac{2+3+1}{2}=3团赁,中位數(shù)剛好是左邊最大的值
當m+n為偶數(shù)時育拨,比如2+2,left\_size=\frac{2+2+1}{2}=2欢摄,左邊剛好有一半數(shù)據(jù)熬丧,中位數(shù)為左邊最大和右邊最小的平均值。

由于左邊元素個數(shù)left\_size是確定的剧浸,當我門在nums1中隨便劃分锹引,確定nums1中左邊元素個數(shù)時(i)矗钟,nums2中左邊元素的個數(shù)也隨之確定(j=left\_size-i)唆香,因為i是在nums1中劃分的,為了避免j超出nums2的長度范圍吨艇,都默認nums1的元素個數(shù)小于nums2(即m <= n)躬它。

因此我們可以在nums1中不停的移動i,來不停劃分nums1东涡,并根據(jù)計算出來的j劃分nums2冯吓,并檢驗劃分后的左邊最大值小于右邊最小值是否滿足(等價于nums1[i-1] <= nums2[j]\ and \ nums2[j-1] <= nums1[i])倘待,如果滿足就找到了合適的劃分。就可以根據(jù)m+n的奇偶性來計算中位數(shù):

  1. m+n為偶數(shù)组贺,返回左邊最大值和右邊最小值的平均值凸舵。
  2. m+n為奇數(shù),返回左邊最大值失尖。

i在nums1中移動啊奄,這個過程可以使用二分查找來加速,定義兩個下標left=0, right=m掀潮,i每次都取left, right的中點菇夸,即i=\frac{left+right}{2}(或i=\frac{left+right+1}{2},根據(jù)left仪吧,right下標的更新方式選擇)庄新。

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        if len(nums1) > len(nums2):
            return self.findMedianSortedArrays(nums2, nums1)
        
        m = len(nums1)
        n = len(nums2)
        left_size = (m+n+1) // 2
        # print("m:{}, n:{}, left_size:{}".format(m, n, left_size))

        left = 0
        right = m

        # nums1[i-1] <= nums2[j] && nums2[j-1] <= nums1[i]
        while left < right:
            i = (left + right + 1) // 2
            j = left_size - i
            # print("left:{}, right:{}, i:{}, j:{}".format(left, right, i, j))
            if nums1[i-1] > nums2[j]:
                right = i-1
            else:
                # nums2[j-1] > nums1[i]
                left = i

        i = left
        j = left_size - left
        nums1_left_max = nums1[i-1] if i > 0 else -2**40
        nums2_left_max = nums2[j-1] if j > 0 else -2**40
        nums1_right_min = nums1[i] if i < m else 2**40
        nums2_right_min = nums2[j] if j < n else 2**40

        if (m+n) % 2 == 1:
            return float(max(nums1_left_max, nums2_left_max))
        else:
            return (float(max(nums1_left_max, nums2_left_max)) + float(min(nums1_right_min, nums2_right_min)))/2

二分查找中點選取技巧

二分查找一般需要計算兩個下標left,right的中點,通常有兩個計算方法薯鼠,

  1. m=\frac{left+right}{2}
  2. m=\frac{left+right+1}{2}

這兩種方法選擇主要和left,right的更新方式有關择诈,主要是為了避免[left, right]區(qū)間只有兩個數(shù)時,算法進入死循環(huán)出皇。

如果我們的left,right按下面的方法更新关划,按m=\frac{left+right}{2}計算抛腕,可能會死循環(huán)。比如循環(huán)迭代到left=m, right=m+1時,some_contition條件滿足傲隶,這時候m=\frac{left+right}{2}=\frac{m+(m+1)}{2} = m,下標left一直停留在m艾少,無法移動疚漆,算法無法終止,進入死循環(huán)奈附。

while left < right:
    if some_condition:
        left = m
    else:
        right = m-1

但是換成m=\frac{left+right+1}{2}就沒有問題全度,這時m=\frac{left+right+1}{2}=\frac{m+(m+1)+1}{2}=m+1,下標leftm移動到m+1斥滤,剛好left == right将鸵,循環(huán)結(jié)束。


同理佑颇,當按下面的方法更新left,right時顶掉,m=\frac{left+right+1}{2}也可能會死循環(huán)。

while left < right:
    if some_condition:
        left = m+1
    else:
        right = m

總結(jié)一句話:下標left設置為中點時挑胸,中點靠右取整(分子+1)痒筒,下標right設置為中點時,中點靠左取整(分子不加1)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末簿透,一起剝皮案震驚了整個濱河市移袍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌老充,老刑警劉巖葡盗,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異啡浊,居然都是意外死亡戳粒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門虫啥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔚约,“玉大人,你說我怎么就攤上這事涂籽∑凰睿” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵评雌,是天一觀的道長树枫。 經(jīng)常有香客問我,道長景东,這世上最難降的妖魔是什么砂轻? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮斤吐,結(jié)果婚禮上搔涝,老公的妹妹穿的比我還像新娘。我一直安慰自己和措,他們只是感情好庄呈,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著派阱,像睡著了一般诬留。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贫母,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天文兑,我揣著相機與錄音,去河邊找鬼腺劣。 笑死绿贞,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的誓酒。 我是一名探鬼主播樟蠕,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼靠柑!你這毒婦竟也來了寨辩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤歼冰,失蹤者是張志新(化名)和其女友劉穎靡狞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體隔嫡,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡甸怕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了腮恩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梢杭。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖秸滴,靈堂內(nèi)的尸體忽然破棺而出武契,到底是詐尸還是另有隱情,我是刑警寧澤荡含,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布咒唆,位于F島的核電站,受9級特大地震影響释液,放射性物質(zhì)發(fā)生泄漏全释。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一误债、第九天 我趴在偏房一處隱蔽的房頂上張望浸船。 院中可真熱鬧,春花似錦寝蹈、人聲如沸糟袁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽项戴。三九已至,卻和暖如春槽惫,著一層夾襖步出監(jiān)牢的瞬間周叮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工界斜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留仿耽,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓各薇,卻偏偏與公主長得像项贺,于是被迫代替她去往敵國和親君躺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容