回溯算法学习笔记
學習資料來源
代碼隨想錄 - 關于回溯算法,你該了解這些!
什么是回溯法
回溯(backtracking)法又稱回溯搜索法,它是一種搜索的方式。
回溯法不容易,但回溯法就是暴力解法。
回溯與遞歸形影不離。
backtracking
英 [?b?ktr?k??] 美 [?b?ktr?k??]
v. 原路返回;折回;折返;(屈于壓力而)改變聲明(或主張),出爾反爾;退縮
backtrack的現在分詞
回溯法的效率
雖然回溯法難懂費解,但是它不是高效的算法。
因為回溯的本質是窮舉,窮舉所有可能,然后選出心儀的答案。如果想讓回溯法高效一些,可以加一些剪枝的操作,但也改不了回溯法就是窮舉的本質。
既然回溯法并不高效為何還要用它呢?因為別無選擇。一些問題除了暴力搜索,就沒有其它更高效的解法。
回溯法解決的問題
回溯法,一般可以解決如下幾種問題:
- 組合問題:N個數里面按一定規則找出k個數的集合
- 排列問題:N個數按一定規則全排列,有幾種排列方式
- 切割問題:一個字符串按一定規則有幾種切割方式
- 子集問題:一個N個數的集合里有多少符合條件的子集
- 棋盤問題:N皇后,解數獨等等
注意,組合與排序的區分。
組合是不強調元素順序的,排列是強調元素順序。
例如:{1, 2} 和 {2, 1} 在組合上,就是一個集合,因為不強調順序,而要是排列的話,{1, 2} 和 {2, 1} 就是兩個集合了。
助記:組合無序,排列有序。
如何理解回溯法
回溯法解決的問題都可以抽象為樹形結構。因為回溯法解決的都是在集合中遞歸查找子集,集合的大小就構成了樹的寬度,遞歸的深度也就構成的樹的深度。
遞歸就要有終止條件,所以必然是一顆高度有限的樹。
回溯法模板
回溯三部曲:
助記:一位中國名人,給美國送終,創造歷史。
回溯函數模板返回值以及參數(函數簽名)
在回溯算法中,回溯函數一般情況下命名為backtracking,返回值一般為void,至于函數參數一開始不容易確定,所以一般先寫邏輯,參數隨后按需添加。
//回溯函數簽名示例 void backtracking(參數 ...){}回溯函數終止條件
什么時候達到了終止條件,樹中就可以看出,一般來說搜到葉子節點了,也就找到了滿足條件的一條答案,把這個答案存放起來,并結束本層遞歸。
if (終止條件) {存放結果;return; }回溯搜索的遍歷過程
前文談到,回溯法一般是在集合中遞歸搜索,集合的大小構成了樹的寬度,遞歸的深度構成的樹的深度。
從圖中看出,for循環理解成橫向遍歷,backtracking(遞歸)則是縱向遍歷,這樣就把這棵樹全遍歷完了,一般來說,搜索葉子節點就是找的其中一個結果了。
for (選擇:本層集合中元素(樹中節點孩子的數量就是集合的大小)) {處理節點;backtracking(路徑,選擇列表); // 遞歸回溯,撤銷處理結果 }總結
回溯算法模板框架如下:
void backtracking(參數) {if (終止條件) {存放結果;return;}for (選擇:本層集合中元素(樹中節點孩子的數量就是集合的大小)) {處理節點;backtracking(路徑,選擇列表); // 遞歸回溯,撤銷處理結果} }這份模板很重要,日后用到回溯法題目都靠它了。
經典題目
總結
- 上一篇: 《Python Cookbook 3rd
- 下一篇: 《机器学习实战》笔记(04):基于概率论