回溯演算法,從入門到精通

2021-09-26 14:44:14 字數 2912 閱讀 6014

回溯演算法在資料結構中式一種常用的演算法,也是一種暴力求解法,基本思想是深度遍歷,選擇一條路一步一步走,當走不通的時候或者已經求的正確的結果,返回上一步,接著選擇另一條路走,直到遍歷完所有節點。

回溯演算法是一種思想,真正用**實現的時候,大多時候都需要用的方法是遞迴。

一. 回溯演算法最出名的是8皇后問題,8皇后問題是在8*8格的棋盤上擺放8個皇后,使得這個8個皇后不在同一行上,也不在不一列上,也不在同乙個對角線上,問有多少種擺法?

這個問題的解法是典型的回溯演算法:

在第一行的某乙個位置放置乙個皇后,當然是從第乙個位置開始。

接著在第二行的找乙個可以擺放皇后的位置,條件就是不在同一行,不在不一列也不在同一斜線上,如果找到則進行下一行的查詢,如果找不到,則回退到第一行的位置重新查詢第乙個皇后的位置,依次類推,直到8個 皇后都放到棋盤上。

**入下:

上面的**最主要的方法是recursionqueen,recursion是遞迴的意思,想象一下8*8的棋盤,引數row為0,從第一行開始,第一行的第乙個位置符合條件,放置乙個皇后,接著遞迴呼叫recursionqueen,row引數為1代表第二行,第二行的第一列檢查不符合條件,因為位於同一列,接著看第二列,同樣不符合條件,接著看看第三列,符合條件,接著在遞迴呼叫recursionqueen,row為2表示第三行,放置第三個皇后,一次類推,直到第八行,第8個皇后符合條件之後,這就找出了第一種正確的擺放位置。

刪除最後乙個皇后,在第8行接著找,直到遍歷完第8行找到全部的擺放位置。第8行遍歷完之後,也就走完了for迴圈,刪除第7行存在列表中皇后,在第七行接著尋找下乙個符條件的皇后,找到之後接著在遞迴呼叫recursionqueen這個方法,尋找第8行符合條件的皇后。等到第7行遍歷完了之後接著刪除第六行的皇后,接著第六行遍歷,尋找第六行下乙個符合條件的皇后,一次類推即可。

以上就是8皇后問題,寫的有點繞,多讀幾遍總能讀懂。

在做幾個回溯問題,鞏固一下:

二. 看下leetcode中的17. **號碼的字母組合這個問題,問題描述如下:

給定乙個僅包含數字 2-9 的字串,返回所有它能表示的字母組合。

給出數字到字母的對映如下(與**按鍵相同)。注意 1 不對應任何字母。

輸入:「23」

輸出:[「ad」, 「ae」, 「af」, 「bd」, 「be」, 「bf」, 「cd」, 「ce」, 「cf」].

這個問題的解法和8皇后問題類似,比如輸入為23的時候,2中的所有字母代表一行,3中的所有字母代表第二行,那麼就可以一次遞迴呼叫某一行的字母進行組合,**入下:

上面的**也不是很難理解,每乙個數字代表幾個字母,用其中的字母來進行迴圈組合,一次遞迴呼叫,當組合的長度和給的digits長度一致的時候,說明這次組合成功,並刪除最後乙個字母,接著迴圈,尋找下乙個符合條件的字母。

三. 在看乙個leetcode中37. 解數獨 :

編寫乙個程式,通過已填充的空格來解決數獨問題。

乙個數獨的解法需遵循如下規則:

數字 1-9 在每一行只能出現一次。

數字 1-9 在每一列只能出現一次。

數字 1-9 在每乙個以粗實線分隔的 3x3 宮內只能出現一次。

空白格用 『.』 表示。

**入下:

遍歷二維陣列,當遇到點的時候,從1到9開始嘗試,判斷是不是滿足條件,如果滿足,用當前的數字替換點,

如果遍歷完了一到9,還是沒有符合條件的,則返回false,證明此路不通,開始回溯,把已經負責的數字用點還原回去,在接著從1到9中尋找合適的數字

如此遞迴回溯,直到找到合適的為止。

四。 再看乙個39. 組合總和

給定乙個無重複元素的陣列 candidates 和乙個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。

candidates 中的數字可以無限制重複被選取。

說明:所有數字(包括 target)都是正整數。

解集不能包含重複的組合。

示例 1:

輸入: candidates = [2,3,6,7], target = 7,

所求解集為:

[[7],

[2,2,3]

]示例 2:

輸入: candidates = [2,3,5], target = 8,

所求解集為:

[[2,2,2,2],

[2,3,3],

[3,5]

]這道題目用回溯演算法也很簡單,思想是從第乙個元素開始,如果比目標值小加到列表中,遞迴遍歷,並把目標值和第乙個元素的差值,還有開始遍歷的起始位置傳遞過去,

2. 從起始位置開始遍歷,和目標值比較,

3. 如果和目標值相等,找到對應的素組,然後刪除列表的最後乙個元素,接著遍歷

4. 如果比目標值大的話,忽略,繼續遍歷

5. 當一次迴圈做完,刪除上一次遞迴插入的元素值

**入下:

上面的**可以排序也可以不排序。 如果傳值start,每次遞迴呼叫都加1的話就成了不重複的元素了。

回溯演算法看這幾個例子就差不多了吧。還想刷題鞏固的話 可以看leetcode上面搜尋關於回溯的題練習。

Nginx從入門到精通

1 nginx配置檔案載入機制 採用nginx s reload命令載入nginx的配置檔案,master程序讀取配置檔案,建立新的worker程序,向老的worker程序傳送shutdown命令。老的worker程序不再接受新的請求,待老的請求處理完成後,就會停掉。2 location匹配機制 當...

scrot 從入門到精通

無論是撰寫技術教程,還是展示桌面或應用,恐怕 scrot 都是必不可少的工具。scrot 是螢幕抓圖工具中的 皎皎 佼佼者,它小巧而不失為強大,精練而不缺少靈活。scrot 主要用在命令列下,它使用 imlib2 庫來抓取並儲存影象。在 ubuntu 中,可以使用sudo apt get insta...

mysql從入門到精通

在sql語言中,用join實現表與表的關聯,用on指定聯合表的查詢條件,如 實現三表聯查,可以用table1.table2.來排列 顯示資訊的先後順序 select from user left join address on user id address.user id left join us...