面試題解| Median of two Sorted Arrays

2021-01-14 LintCode領扣

解題思路分析


這道題的直觀解法:就是掃一遍兩個數組,找到中間位置的那一個/兩個數,然後得到中位數。時間複雜度是 O(m+n),其中 m 和 n 分別是數組 A 和數組 B 的長度。


深入分析


但是!面試官會這麼輕易就放過你嗎?顯然是不可能滴~~小編偷看了一下題目描述下的「challenge」標籤,原來這道題的最優解是 O(log(m + n)) 的複雜度。


(m + n) 是倆數組合併後的總長度  L,看到 O(log L) 這樣的複雜度,而且還是有序數組,能想到哪個算法嗎?沒錯,就是二分查找!那讓我們來試試——


1.如果我取出 A[i] ,用二分查找在數組 B 中找到 A[i] 可以插入的位置,假設 A[i] 在 B 中的插入位置是 j,那麼 A[i] 在整個合併數組中的位置就是 (i + j) ,因為要求的中位數的位置是 (m + n) / 2,通過比較 (i + j) 和 (m + n) / 2 的大小可以每次捨棄 A 的一部分,從而收斂數組 A。用同樣的方法可以收斂數組 B。但是這樣的複雜度是 O(log m * log n),複雜度大於 O(log(m + n)),顯然不是最優的。


2.那如果不是直接使用二分查找算法,而是借用二分查找的思想呢?就是每次有選擇地捨棄掉數組的一部分,從而達到收斂數組縮小查找範圍的效果


i.我們重新看題目,要找中位數,就是要找第 k 大的數(k = (L / 2 + 1)


其中L 是上面提到的合併後新數組的長度,當 L 是偶數時,要求第 (L / 2) 大和第 (L / 2 + 1) 大的兩個數)。


當我們捨棄掉一部分,假設捨棄部分的長度為 length,那麼接下來就是在剩下的數組裡求第 (k - length) 大的數。逐層縮小範圍,直到兩數組其中一個走完,或者要求的是第 1 大的元素,就可以直接返回結果了。


ii.那如何「選擇」要捨棄哪部分呢?


既然是要找合併後的數組 C 的第 k 大元素,即 C[k-1],那如果我們從 A 和 B 中分別取前 k/2 個元素,其中必然有一部分是是在數組 C 的前 k 個數裡。


設 mid = k / 2,當 A[mid - 1] < B[mid - 1] 時,可以斷定 A 的前 mid 個元素是在 C 的前 k 個數裡(此處可用反證法得證),那麼我們則捨棄 A 的前 mid 個元素。反之則捨棄 B 的前 mid 個元素。


現在數組 A 或者 B 已經捨棄掉 k/2 個元素,縮小查找範圍了,那接下來可以按照同樣的方法繼續選擇嗎?當然!現在剩下總共 (L - mid) 個元素,且 A 和 B 依舊有序,要找的是第 (k - mid) 大的元素,所以我們可以按照上面的方法繼續遞歸選擇下去,直到找到目標元素!代碼如下:



參考程序


class Solution:
    """
    @param A: An integer array.
    @param B: An integer array.
    @return: a double whose format is *.5 or *.0
    """
    def findMedianSortedArrays(self, A, B):
        m, n = len(A), len(B)
        if m == 0 and n == 0:
            return 0.0

        total = m + n
        if total % 2 == 1:
            return self.kth_largest(A, B, total / 2 + 1) * 1.0
        else:
            a = self.kth_largest(A, B, total / 2)
            b = self.kth_largest(A, B, total / 2 + 1)
            return (a + b) / 2.0

    def kth_largest(self, A, B, kth):
        m, n = len(A), len(B)
        if m == 0:
            return B[kth-1]
        if n == 0:
            return A[kth-1]
        if kth == 1:
            return min(A[0], B[0])

        mid = kth / 2
        a, b = float("inf"), float("inf")
        if m >= mid:
            a = A[mid - 1]
        if n >= mid:
            b = B[mid - 1]
        if a < b:
            return self.kth_largest(A[mid:], B, kth - mid)
        else:
            return self.kth_largest(A, B[mid:], kth - mid)


複雜度分析:每次從合併後數組 C 裡減少 k/2 個元素,直到找到目標元素。所以時間複雜度是 O(log L) = O(log (m + n)) !


面試官角度分析


這道題是二分方法的拓展運用,並且需要對二分有比較高的理解,比如怎麼樣通過猜測試一試二分來解決問題。如果能夠達到二分的方法,當然必然是Strong Hire的等級。

相關題目

可掃描下列二維碼直接進入

若有其他問題可留言後臺




相關焦點

  • leetCode第4題:Median of Two Sorted Arrays
    原題:There are two sorted arrays A and B of size m and n respectively
  • 直擊LeetCode最經典二分法算法題:Median of Two Sorted Arrays
    題目詳情原題如下:There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays.
  • 網際網路公司最常見的面試算法題大集合
    很多求職者都會在LeetCode刷上一遍,面試官也喜歡在上面挑選各類題目。LeetCode是一個美國的在線編程網站,收集了各個大廠的筆試面試題,對找工作的畢業生和開發者來說,非常有價值。不過LeetCode上面的題目很多都是考察應聘者對基礎知識的應用,適合進行練習編程基礎或者準備面試。
  • 面試近百場才明白 原來這5點最重要丨Data Scientist求職親述
    Data Scientist面試的基本流程包括: 其中,電話面試主要是聊聊簡歷,問問機器學習概率統計,寫寫代碼。Homework Assignment, 通常是給一個簡化但與實際工作相關的問題,根據給出的數據進行建模、分析、完成報告。Onsite interview裡每一輪面試的側重點都會有所不同,但是基本上是電話面試的擴展版。
  • python實踐分享:關於排序算法,怎麼選擇sort()或者sorted()?
    各種排序算法以及它們的時間複雜度分析是很多企業面試人員在面試時候經常會問到的問題,這也不難理解,在實際的應用過程中確實會遇到各種需要排序的情況,如按照字母表輸出一個序列、對記錄的多個欄位排序等。還好,Python中的排序相對簡單,常用的函數有 sort()和sorted()兩種。這兩種函數並不完全相同,各有各的用武之地。我們來具體分析一下。
  • 程式設計師面試通關的 101 道真題
    (https://www.java67.com/2015/08/how-to-swap-two-integers-without-using.html)如何檢查兩個矩形是否重疊?(https://javarevisited.blogspot.com/2016/10/how-to-check-if-two-rectangle-overlap-in-java-algorithm.html)如何設計一臺自動售貨機?
  • average, mean, median, medium與 middle
    average、 mean、 median、 medium、 middle(1)從大概意思來看:average、mean 側重「平均的、平均值」的意思;median 側重「中間的、中間值」的意思;middle、medium 側重「中等的」的意思。至於怎麼理解這三個意思的區別?
  • 「去公式化」 分析化學教材及題解背後的故事
    2019年8月,《分析化學題解——基於去公式化計算策略》由科學出版社出版。  編寫題解是大量、多類型題目的集中求解,這為我提供了一個極好的機會去檢驗、反思和提升「去公式化」課程體系。此外,需要補充不少新的教研成果,採納很多教師和學生讀者的寶貴建議。所以,教材再版與題解撰寫同時進行。  我原以為教材再版只是修補增刪,然而事實並非如此。
  • 常考算法面試題系列:鍊表的操作
    題目列表面試題 02.02. 返回倒數第 k 個節點[4]1. 反轉鍊表使用迭代:在遍歷列表時,將當前節點的 next 指針改為指向前一個元素。由於節點沒有引用其上一個節點,因此必須事先存儲其前一個元素。在更改引用之前,還需要另一個指針來存儲下一個節點。不要忘記在最後返回新的頭引用。
  • JavaScript 面試中常見算法問題詳解
    JavaScript 面試中常見算法問題詳解,翻譯自 https://github.com/kennymkchan/interview-questions-in-javascript
  • Number of Squareful Arrays 平方數組的個數
    };Github 同步地址:https://github.com/grandyang/leetcode/issues/996類似題目:PermutationsPermutations II參考資料:https://leetcode.com/problems/number-of-squareful-arrays
  • 面試英語:面試官和求職者的英語對話
    面試英語:面試官和求職者的英語對話  Dialogue A  I:De you have any particular conditions that you would like our company to take into consideration?
  • PTA函數題之縮寫詞滿分題解(Python3)
    圖片來源於pixabay滿分題解:該題需要對字符串內置函數的了解,字符串內置函數title()是可以對字符串的每個單詞首字母進行大寫處理,這就非常符合題目要求了,同時輸入的短語的單詞之間有空格間隔開,所以用
  • 一位硬體工程師的面試經歷
    下面主要說一下我筆試面試公司的過程,本篇主要側重筆試(面試稍後補上),按時間先後順序: 1 、華為: 硬體沒有筆試,首先是一面,技術面,大概只有15分鐘,然後性格測試(會刷人),但一般性格測試可以做兩遍。最後綜合面試了,一般大概也只有一刻鐘。