# 回溯算法框架
result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择
目录
题型一:排列、组合、子集相关问题
剑指 Offer 38. 字符串的排列
# 回溯法见评论
class Solution:
def permutation(self, s: str) -> List[str]:
self.res=[]
def backtrack(s,path):
if not s:
self.res.append(path)
seen=set() #对子序列去重操作
for i in range(len(s)):
if s[i] in seen:continue
seen.add(s[i])
backtrack(s[:i]+s[i+1:], path+s[i])
backtrack(s, '')
return self.res
46. 全排列–类似上面38题
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
self.res=[]
def backtrack(s,path):
if not s:
return self.res.append(path)
# seen=set() #把所有的注释取消也是对的
for i in range(len(s)):
# if s[i] in seen :continue
# seen.add(s[i])
backtrack(s[:i]+s[i+1:], path+[s[i]])
backtrack(nums, [])
return self.res
47. 全排列 II
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
nums.sort()
n=len(nums)
res=[]
def backtrack(s,path):
if not s and path not in res:
res.append(path)
for i in range(len(s)):
backtrack(s[:i]+s[i+1:],path+[s[i]])
backtrack(nums,[])
return res
39. 组合总和
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
n=len(candidates)
res=[]
def backtrack(i,tmp_sum,tmp):
if tmp_sum>target or i==n:
return
if tmp_sum==target:
return res.append(tmp)
for j in range(i,n):
if tmp_sum+candidates[j]>target:
break
backtrack(j,tmp_sum+candidates[j],tmp+[candidates[j]])
backtrack(0,0,[])
return res
40. 组合总和 II
# 推荐
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
if not candidates:
return []
candidates.sort()
n = len(candidates)
res = []
def backtrack(i, tmp_sum, tmp_list):
if tmp_sum == target:
res.append(tmp_list)
return
for j in range(i, n):
if tmp_sum + candidates[j] > target : break
if j > i and candidates[j] == candidates[j-1]:continue
backtrack(j + 1, tmp_sum + candidates[j], tmp_list + [candidates[j]])
backtrack(0, 0, [])
return res
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
def dfs(begin,path,residue):
if residue==0:
res.append(path[:])
return
for i in range(begin,n):
if candidates[i]>residue:
break
if i>begin and candidates[i-1]==candidates[i]:
continue
path.append(candidates[i])
dfs(i+1,path,residue-candidates[i])
path.pop()
n=len(candidates)
if n==0:return []
candidates.sort()
res=[]
dfs(0,[],target)
return res
78. 子集
# 回溯
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
n = len(nums)
def helper(i, tmp):
res.append(tmp)
for j in range(i, n):
helper(j + 1,tmp + [nums[j]] )
helper(0, [])
return res
Python itertools模块combinations方法:添加链接描述
# 库函数
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
for i in range(len(nums)+1):
for tmp in itertools.combinations(nums, i):
res.append(tmp)
return res
90. 子集 II
# 法一
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
n=len(nums)
res=[]
def backtrack(i,tmp):
res.append(tmp)
for j in range(i,n):
if j>i and nums[j]==nums[j-1]:continue
backtrack(j+1,tmp+[nums[j]])
backtrack(0,[])
return res
# 法二
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
n=len(nums)
res=[]
def backtrack(i,tmp):
if tmp not in res:
res.append(tmp)
for j in range(i,n):
backtrack(j+1,tmp+[nums[j]])
backtrack(0,[])
return res
77. 组合
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res = []
def backtrack(nums, tmp):
if not nums:
res.append(tmp)
return
for i in range(len(nums)):
backtrack(nums[:i] + nums[i+1:], tmp + [nums[i]])
backtrack(nums, [])
return res