刷題總結——回溯演算法

haydenhs發表於2024-10-26

總論

  • 增量構造答案
  • 關注邊界條件的邏輯
    • 當前操作?(選/不選,列舉選哪一個)
    • 子問題?
    • 下一個子問題?
  • 用什麼資料結構儲存搜尋路徑?
  • 時間複雜度計算:搜尋樹節點數*生成答案需要的時間

題目分類

可以分成子集型、排列型和組合型三種:

回溯問題 時間複雜度O() 解法
子集 LC78 n x 2^n 記錄下標i+1
子集 II(有重複) LC90 n x 2^n 同上+hash
排列 面試題08.07 n x n! Vis陣列管理或者swap下標
排列II(有重複) 面試題08.08 n x n! 同上+hash
組合型 括號生成LC22 C(2n,n) 剪枝+葉子節點push
  • 使用hash可以理解為一種剪枝方式,主要是去掉重複元素
  • 組合型需要對普通回溯結果根據預設條件進行剪枝

子集型

從執行和答案兩個角度考慮問題:

  • 選與不選是從葉子節點的角度考慮,在葉子節點再push答案
  • 列舉選哪個是從回溯過程的角度考慮,需要考慮下標管理,從更大的下標中構造子集

注意使用位運算的迭代思路:不回溯,直接使用2^n位運算計算出上限,然後for迴圈變數作為mask依次處理

組合型

  • 從n個數字中選擇k個數的組合,可以認為是尋找路徑長度固定為k的子集
  • 有額外剪枝的可能性,因為選擇有順序(組合保證了順序的存在,順序起到了去重的效果)
    • 組合: 每次選的範圍縮小,都在0, i-1內,人為規定的逆序
    • 括號生成:狀態改變時候的性質
  • 時間複雜度=路徑長度X葉子個數,即k X C(n, k)

排列型

可以重複,但順序不同,因此需要有一個結構儲存接下來還能儲存哪些數:

  • path:記錄搜尋路徑
  • 集合s:hash記錄未選的數字/布林陣列

全排列O(n*n!): 節點路徑長度x葉子節點個數

注意全排列可以使用交換法實現,比較巧妙的處理

參考

  1. https://www.bilibili.com/video/BV1xG4y1F7nC/?vd_source=c80c62eac86a4ba033ab112349bbdd9f
  2. https://www.bilibili.com/video/BV1mG4y1A7Gu/?vd_source=c80c62eac86a4ba033ab112349bbdd9f&spm_id_from=333.788.videopod.sections
  3. https://leetcode.cn/problems/permutation-i-lcci/solutions/406850/quan-pai-lie-jiao-huan-fa-qing-xi-tu-shi-by-chen-k/?envType=problem-list-v2&envId=xb9lfcwi

相關文章