回溯算法,從入門到精通

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

回溯算法是一種思想,真正用代碼實現的時候,大多時候都須要用的方法是遞歸。算法

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

這個問題的解法是典型的回溯算法:數據結構

  1. 在第一行的某一個位置放置一個皇后,固然是從第一個位置開始。
  2. 接着在第二行的找一個能夠擺放皇后的位置,條件就是不在同一行,不在不一列也不在同一斜線上,若是找到則進行下一行的查找,若是找不到,則回退到第一行的位置從新查找第一個皇后的位置,依次類推,直到8個 皇后都放到棋盤上。 代碼入下: 在這裏插入圖片描述 上面的代碼最主要的方法是recursionQueen,recursion是遞歸的意思,想象一下8*8的棋盤,參數row爲0,從第一行開始,第一行的第一個位置符合條件,放置一個皇后,接着遞歸調用recursionQueen,row參數爲1表明第二行,第二行的第一列檢查不符合條件,由於位於同一列,接着看第二列,一樣不符合條件,接着看看第三列,符合條件,接着在遞歸調用recursionQueen,row爲2表示第三行,放置第三個皇后,一次類推,直到第八行,第8個皇后符合條件以後,這就找出了第一種正確的擺放位置。
  3. 刪除最後一個皇后,在第8行接着找,直到遍歷完第8行找到所有的擺放位置。第8行遍歷完以後,也就走完了for循環,刪除第7行存在列表中皇后,在第七行接着尋找下一個符條件的皇后,找到以後接着在遞歸調用recursionQueen這個方法,尋找第8行符合條件的皇后。等到第7行遍歷完了以後接着刪除第六行的皇后,接着第六行遍歷,尋找第六行下一個符合條件的皇后,一次類推便可。 以上就是8皇后問題,寫的有點繞,多讀幾遍總能讀懂。 在作幾個回溯問題,鞏固一下:

二. 看下LeetCode中的17. 電話號碼的字母組合這個問題,問題描述以下:3d

給定一個僅包含數字 2-9 的字符串,返回全部它能表示的字母組合。 給出數字到字母的映射以下(與電話按鍵相同)。注意 1 不對應任何字母。 在這裏插入圖片描述 輸入:"23" 輸出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].blog

這個問題的解法和8皇后問題相似,好比輸入爲23的時候,2中的全部字母表明一行,3中的全部字母表明第二行,那麼就能夠一次遞歸調用某一行的字母進行組合,代碼入下:排序

在這裏插入圖片描述 上面的代碼也不是很難理解,每個數字表明幾個字母,用其中的字母來進行循環組合,一次遞歸調用,當組合的長度和給的digits長度一致的時候,說明此次組合成功,並刪除最後一個字母,接着循環,尋找下一個符合條件的字母。遞歸

三. 在看一個LeetCode中37. 解數獨 : 編寫一個程序,經過已填充的空格來解決數獨問題。圖片

一個數獨的解法需遵循以下規則:字符串

數字 1-9 在每一行只能出現一次。 數字 1-9 在每一列只能出現一次。 數字 1-9 在每個以粗實線分隔的 3x3 宮內只能出現一次。 空白格用 '.' 表示。 在這裏插入圖片描述

代碼入下: 在這裏插入圖片描述

  1. 遍歷二維數組,當遇到點的時候,從1到9開始嘗試,判斷是否是知足條件,若是知足,用當前的數字替換點,
  2. 遞歸調用,由於上一個點已經被替換了,接着遍歷二維數組,尋找下一個是的點的位置,找到以後在遍歷1到9查找符合條件的字符,找到以後接着再遞歸,仍是走2
  3. 若是遍歷完了一到9,仍是沒有符合條件的,則返回false,證實此路不通,開始回溯,把已經負責的數字用點還原回去,在接着從1到9中尋找合適的數字
  4. 如此遞歸回溯,直到找到合適的爲止。

四。 再看一個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上面搜索關於回溯的題練習。

再小的努力,乘以365天也會變的偉大!歡迎關注個人公衆號 :北風中獨行的蝸牛 在這裏插入圖片描述

相關文章
相關標籤/搜索