總論
- 增量構造答案
- 關注邊界條件的邏輯
- 當前操作?(選/不選,列舉選哪一個)
- 子問題?
- 下一個子問題?
- 用什麼資料結構儲存搜尋路徑?
- 時間複雜度計算:搜尋樹節點數*生成答案需要的時間
題目分類
可以分成子集型、排列型和組合型三種:
回溯問題 | 時間複雜度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葉子節點個數
注意全排列可以使用交換法實現,比較巧妙的處理
參考
- https://www.bilibili.com/video/BV1xG4y1F7nC/?vd_source=c80c62eac86a4ba033ab112349bbdd9f
- https://www.bilibili.com/video/BV1mG4y1A7Gu/?vd_source=c80c62eac86a4ba033ab112349bbdd9f&spm_id_from=333.788.videopod.sections
- 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