目录
前言
一、回溯模版:排列型回溯(1,3,5,6,8),子集型回溯(2,4,7),组合型回溯。
二、回溯例题:全排列,子集,电话号码的字母组合,组合总和,括号生成,单词搜索,分割回文串,N 皇后。
一、回溯模版
1. 排列型回溯
class Solution:
def HanShu(self, nums):
res = []
n = len(nums)
path = [0] * n # [0]中数值0可变
def dfs(i):
if i == n:
res.append(path[:])
return
for c in nums:
path[i] = c
dfs(i+1)
dfs(0)
return res
2. 子集型回溯
例题:......
class Solution:
def HanShu(self, nums):
res = []
n = len(nums)
path = []
def dfs(i):
res.append(path[:])
if i == n:
# res.append(path[:])
return
for j in range(i, n): ###
path.append(num[j]) ###
dfs(j+1) ###
path.pop() ###
dfs(0)
return res
3. 组合型回溯
二、回溯例题
1. 全排列(排列型回溯)
class Solution(object):
def permute(self, nums):
# 方法(1):通过 itertools.permutations 实现
# from itertools import permutations
# return list(permutations(nums))
# 方法(2):回溯
res = []
n = len(nums)
path = [0] * n
def dfs(i, nums):
if i == n:
res.append(path[:])
return
for c in nums:
path[i] = c
dfs(i+1, nums-{c})
return res
return dfs(0, set(nums))
2. 子集(子集型回溯)
class Solution(object):
def subsets(self, nums):
n = len(nums)
res = []
path = []
def dfs(i):
res.append(path[:])
if i==n:
return
for j in range(i, n):
path.append(nums[j])
dfs(j+1)
path.pop()
return res
return dfs(0)
3. 电话号码的字母组合(排列型回溯)
原题链接:17. 电话号码的字母组合 - 力扣(LeetCode)
dicts = {1:'', 2: 'abc', 3: 'def', 4: 'ghi', 5: 'jkl', 6: 'mno', 7: 'pqrs', 8: 'tuv', 9: 'wxyz'}
class Solution(object):
def letterCombinations(self, digits):
if not digits:
return []
n = len(digits)
res = []
path = ['']*n
def dfs(i):
if i==n:
res.append(''.join(path))
return
for c in dicts[int(digits[i])]:
path[i] = c
dfs(i+1)
return res
return dfs(0)
4. 组合总和(子集型回溯)
class Solution(object):
def combinationSum(self, candidates, target):
n = len(candidates)
res = []
path = []
def dfs(i):
if sum(path) == target:
res.append(path[:])
return
if sum(path) > target:
return
for j in range(i, n):
path.append(candidates[j])
dfs(j)
path.pop()
return res
return dfs(0)
5. 括号生成(排列型回溯)
class Solution(object):
def generateParenthesis(self, n):
m = 2*n
res= []
path = ['']*m
def dfs(i, open):
if i==m:
res.append(''.join(path[:]))
return
if open<n:
path[i] = '('
dfs(i+1, open+1)
if i-open<open:
path[i] = ')'
dfs(i+1, open)
return res
return dfs(0, 0)
6. 单词搜索(排列型回溯)
class Solution(object):
def exist(self, board, word):
def dfs(x, y, k):
if k==len(word):
return True
if not (0 <= x < m and 0 <= y <n and board[x][y]==word[k]):
return False
board[x][y] = ''
res = dfs(x+1, y, k+1) or dfs(x-1, y, k+1) or dfs(x, y+1, k+1) or dfs(x, y-1, k+1)
board[x][y] = word[k]
return res
m,n = len(board), len(board[0])
for x in range(m):
for y in range(n):
if dfs(x, y, 0):
return True
return False
7. 分割回文串(子集型回溯)
原题链接:131. 分割回文串 - 力扣(LeetCode)
class Solution(object):
def partition(self, s):
n = len(s)
res = []
path = []
def dfs(i):
if i==n:
res.append(path[:])
return
for j in range(i, n):
s_ = s[i:j+1]
if s_==s_[::-1]:
path.append(s_)
dfs(j+1)
path.pop()
return res
return dfs(0)
8. N 皇后(排列型回溯)
class Solution(object):
def solveNQueens(self, n):
res = []
cols = [0] * n
def is_valid(r, c):
for R in range(r):
C = cols[R]
if c+r==C+R or c-r==C-R: # 左 / 右斜对角线
return False
return True
def dfs(r, s):
if r == n:
res.append(['.'*c+'Q'+'.'*(n-c-1) for c in cols])
return
for c in s:
if is_valid(r, c):
cols[r] = c
dfs(r+1, s-{c})
return res
return dfs(0, set(range(n)))