LeetCode Hot100 ---- 回溯算法专题
回溯算法是什么?解決回溯算法相關的問題有什么技巧?如何學習回溯算法?回溯算法代碼是否有規律可循?
其實回溯算法其實就是我們常說的 DFS 算法,本質上就是一種暴力窮舉算法。
解決一個回溯問題,實際上就是一個決策樹的遍歷過程。你只需要思考 3 個問題:
1、路徑:也就是已經做出的選擇。
2、選擇列表:也就是你當前可以做的選擇。
3、結束條件:也就是到達決策樹底層,無法再做選擇的條件。
如果你不理解這三個詞語的解釋,沒關系,我們后面會用「全排列」和「N 皇后問題」這兩個經典的回溯算法問題來幫你理解這些詞語是什么意思,現在你先留著印象。
代碼方面,回溯算法的框架:(博客參考labuladong)
result = [] def backtrack(路徑, 選擇列表):if 滿足結束條件:result.add(路徑)returnfor 選擇 in 選擇列表:做選擇backtrack(路徑, 選擇列表)撤銷選擇其核心就是 for 循環里面的遞歸,在遞歸調用之前「做選擇」,在遞歸調用之后「撤銷選擇」,特別簡單。
幾道典型問題:
??? 一.46. 全排列
??? 二.面試題 08.12. 八皇后
??? 三.22. 括號生成
??? 四.面試題38. 字符串的排列
一.46. 全排列
回溯樹:
(子集)輸入一個不包含重復數字的數組,要求算法輸出這些數字的所有子集。
class Solution(object):def subsets(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""res = []def backtrace(nums, start, track):res.append(track[:])for i in range(start, len(nums)):track.append(nums[i])backtrace(nums, i+1, track)track.pop()backtrace(nums, 0, [])return res(組合)輸入兩個數字 n, k,算法輸出 [1..n] 中 k 個數字的所有組合。
class Solution(object):def combine(self, n, k):""":type n: int:type k: int:rtype: List[List[int]]"""res = []def backtrace(n, k, start, track):if k == len(track):res.append(track[:])for i in range(start,n +1 ):track.append(i)backtrace(n, k, i+1, track)track.pop()backtrace(n, k, 1, [])return res
二.面試題 08.12. 八皇后
class Solution:def solveNQueens(self, n: int) -> List[List[str]]:res=[]board=[['.']*n for _ in range(n)]def backtrack(board,row):#結束條件if row==n:temp=[]for ch in board:temp.append("".join(ch))res.append(temp) return for j in range(n):#判斷條件if isValid(board,row,j)==False:continue#做選擇 board[row][j]='Q'#進入下一輪決策backtrack(board,row+1)#撤銷選擇board[row][j]='.'def isValid(board,row,line):#判斷這一列:for i in range(row):if board[i][line]=='Q':return False#判斷這一行for j in range(line):if board[row][j]=='Q':return False#判斷左上的對角線ai=row-1bj=line-1while ai>=0 and bj>=0:if board[ai][bj]=='Q':return Falseai-=1bj-=1#判斷右上的對角線ci=row-1dj=line+1while 0<=ci and dj<n:if board[ci][dj]=='Q':return Falseci-=1dj+=1return Truebacktrack(board,0)return res
函數 backtrack 依然像個在決策樹上游走的指針,通過 row 和 col 就可以表示函數遍歷到的位置,通過 isValid 函數可以將不符合條件的情況剪枝
三.22. 括號生成
明確合法字符串要求:
1、一個「合法」括號組合的左括號數量一定等于右括號數量,這個顯而易見。
2、對于一個「合法」的括號字符串組合p,必然對于任何0 <= i < len 都有:子串p[0…i]中左括號的數量都大于或等于右括號的數量。
算法輸入一個整數n,讓你計算 n對括號能組成幾種合法的括號組合,可以改寫成如下問題:
現在有2n個位置,每個位置可以放置字符(或者),組成的所有括號組合中,有多少個是合法的?
class Solution:def generateParenthesis(self, n: int) -> List[str]:res=[]def backstrack(temp,left,right):#結束條件if len(temp)==2*n:res.append("".join(temp))return#開始進行遍歷#可用的左括號left,可用的右括號rightif left<n:#做選擇temp.append('(')#下一輪決策backstrack(temp,left+1,right)#撤回temp.pop()#同理if right<left:temp.append(')')backstrack(temp,left,right+1)temp.pop()backstrack([],0,0)return res class Solution(object):def generateParenthesis(self, n):""":type n: int:rtype: List[str]"""res=[]def backstrack(temp,left,right):#結束條件if right < left:returnif left < 0 or right < 0:return if left == 0 and right == 0:res.append("".join(temp))return#開始進行遍歷#可用的左括號left,可用的右括號right#做選擇temp.append('(')#下一輪決策backstrack(temp,left-1,right)#撤回temp.pop()temp.append(')')backstrack(temp,left,right-1)temp.pop()backstrack([],n,n)return res
四.面試題38. 字符串的排列
?
?????? ?
-
subsets
-
subsets-ii
-
permutations
-
permutations-ii
-
combination-sum
-
letter-combinations-of-a-phone-number
-
palindrome-partitioning
-
restore-ip-addresses
總結
以上是生活随笔為你收集整理的LeetCode Hot100 ---- 回溯算法专题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [深度学习] FM FFM 算法基本原
- 下一篇: 两轮车概念股票龙头一览表,2022两轮车