LeetCode刷題時遇到的有“名”算法(頻繁更新中。。。)

1. 分治法(240.搜索二維矩陣 II)

思路:

  • 左下角的元素是這一行中最小的元素,同時又是這一列中最大的元素。比較左下角元素和目標:
    • 若左下角元素等於目標,則找到
    • 若左下角元素大於目標,則目標不可能存在於當前矩陣的最後一行,問題規模可以減小爲在去掉最後一行的子矩陣中尋找目標
    • 若左下角元素小於目標,則目標不可能存在於當前矩陣的第一列,問題規模可以減小爲在去掉第一列的子矩陣中尋找目標
  • 若最後矩陣減小爲空,則說明不存在

應用擴展

  • 歸併排序 

2.動態規劃(887. Super Egg Drop )

聯繫

  • 沒有分叉,一路推理 ➜ 〔線性結構〕
  • 看到決策結果有分叉 ➜ 〔樹形結構〕
  • 若在推理過程中,產生交匯 ➜ 〔圖結構〕

3.遞歸回溯(131. 分割回文串)

 特點:

  • 遞歸:在函數的定義中使用函數自身的方法,把規模大的問題轉化爲規模小的子問題來解決。
  • 回溯:從問題的某一種狀態(初始狀態)出發,搜索從這種狀態出發所能達到的所有“狀態”,當一條路走到“盡頭”的時候(不能再前進),再後退一步或若干步,從另一種可能“狀態”出發,繼續搜索,直到所有的“路徑”(狀態)都試探過。

應用

  • 遞歸:漢諾塔
  • 回溯:四/八皇后

4. 前綴樹

特點:

即字典樹,又稱單詞查找樹或鍵樹,是一種樹形結構,是一種哈希樹的變種。典型應用是用於統計和排序大量的字符串(但不僅限於字符串),所以經常被搜索引擎系統用於文本詞頻統計。它的優點是:最大限度地減少無謂的字符串比較,查詢效率比哈希表高。

思想:

空間換時間,利用字符串的公共前綴來降低查詢時間的開銷以達到提高效率的目的。 
它有3個基本性質:

  1. 根節點不包含字符,除根節點外每一個節點都只包含一個字符。
  2. 從根節點到某一節點,路徑上經過的字符連接起來,爲該節點對應的字符串。
  3. 每個節點的所有子節點包含的字符都不相同。

5.大頂堆(378. 有序矩陣中第K小的元素

思路:

設定K容量堆,依次存入大值,多於K個後刪除堆內最大值,排序完成後堆首值即爲矩陣內第K小值。 

注:對於python語言執行速度較差,用大頂堆的思路解決第K小元素問題時運行超時,需安裝如下思路解題:

class Solution:
    def kthSmallest(self, matrix, k):
        """
        :type matrix: List[List[int]]
        :type k: int
        :rtype: int
        """
        lo, hi = matrix[0][0], matrix[-1][-1]
        while lo <= hi:
            mid = lo + (hi-lo)//2
            loc = self.countLower(matrix, mid)
            if loc >= k:
                hi = mid - 1
            else:
                lo = mid + 1
        return lo

    def countLower(self, matrix, num):
        i, j = len(matrix) - 1, 0
        cnt = 0
        while i >= 0 and j < len(matrix[0]):
            if matrix[i][j] <= num:
                cnt += i + 1
                j += 1
            else:
                i -= 1
        return cnt

6.快慢指針(141.環形鏈表)

給定一個鏈表,判斷鏈表中是否有環。爲了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鏈表中沒有環。

思路:

通過使用具有 不同速度 的快、慢兩個指針遍歷鏈表,空間複雜度可以被降低至 O(1)O(1)。慢指針每次移動一步,而快指針每次移動兩步。

如果列表中不存在環,最終快指針將會最先到達尾部,此時我們可以返回 false

現在考慮一個環形鏈表,把慢指針和快指針想象成兩個在環形賽道上跑步的運動員(分別稱之爲慢跑者與快跑者)。而快跑者最終一定會追上慢跑者。這是爲什麼呢?考慮下面這種情況(記作情況 A) - 假如快跑者只落後慢跑者一步,在下一次迭代中,它們就會分別跑了一步或兩步並相遇。

其他情況又會怎樣呢?例如,我們沒有考慮快跑者在慢跑者之後兩步或三步的情況。但其實不難想到,因爲在下一次或者下下次迭代後,又會變成上面提到的情況 A。

複雜度分析

  • 時間複雜度:O(n)O(n), 讓我們將 nn 設爲鏈表中結點的總數。爲了分析時間複雜度,我們分別考慮下面兩種情況。

    • 鏈表中不存在環:
      快指針將會首先到達尾部,其時間取決於列表的長度,也就是 O(n)O(n)。

    • 鏈表中存在環:
      我們將慢指針的移動過程劃分爲兩個階段:非環部分與環形部分:

      1. 慢指針在走完非環部分階段後將進入環形部分:此時,快指針已經進入環中 \text{迭代次數} = \text{非環部分長度} = N迭代次數=非環部分長度=N

      2. 兩個指針都在環形區域中:考慮兩個在環形賽道上的運動員 - 快跑者每次移動兩步而慢跑者每次只移動一步。其速度的差值爲1,因此需要經過 \dfrac{\text{二者之間距離}}{\text{速度差值}}速度差值二者之間距離​ 次循環後,快跑者可以追上慢跑者。這個距離幾乎就是 "\text{環形部分長度 K}環形部分長度 K" 且速度差值爲 1,我們得出這樣的結論 \text{迭代次數} = \text{近似於}迭代次數=近似於 "\text{環形部分長度 K}環形部分長度 K".

    因此,在最糟糕的情形下,時間複雜度爲 O(N+K)O(N+K),也就是 O(n)O(n)。

  • 空間複雜度:O(1)O(1), 我們只使用了慢指針和快指針兩個結點,所以空間複雜度爲 O(1)O(1)。

 7.歸併排序(手懶中。。)

(python,使用list實現鏈表https://blog.csdn.net/dinnerhowe/article/details/58191823

8.快速排序(手懶中。。)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章