理论基础
回溯法也可以叫回溯搜索法,它是一种搜索的方式
回溯是递归的副产品,有递归就有回溯
回溯法的效率:效率并不搞,因为回溯的本质是穷举
回溯法的应用方面:
组合问题:N个数里面按一定规则找出k个数的集合
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
排列问题:N个数按一定规则全排列,有几种排列方式
棋盘问题:N皇后,解数独等等
如何理解回溯法:回溯法解决的问题都可以抽象为树形结构,所有回溯法的问题都可以抽象为树形结构
因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度就构成了树的深度。
77 组合
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
class Solution(object):
def combine(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[List[int]]
"""
result = []
self.backtracking(n,k,1,[],result) #n,k表示n个数,k个数组合
return result
def backtracking(self,n,k,startIndex,path,result):
#startIndex表示当前迭代开始的位置,path表示当前组合路径,result存储最终结果的列表
if len(path) == k: #如果找到一个有效组合,添加到result列表中
result.append(path[:])
return
for i in range(startIndex,n+1): #更新startIndex为i+1,在下一层递归中就不会选择已经选择过得
path.append(i)
self.backtracking(n,k,i+1,path,result)
path.pop() #将最后一个元素移除(回溯)
216 组合总和
class Solution:
def combinationSum3(self, k, n) :
result = [] # 存放结果集
self.backtracking(n, k, 0, 1, [], result)
return result
def backtracking(self, targetSum, k, currentSum, startIndex, path, result):
if currentSum > targetSum: # 剪枝操作
return # 如果path的长度等于k但currentSum不等于targetSum,则直接返回
if len(path) == k:
if currentSum == targetSum:
result.append(path[:])
return
for i in range(startIndex, 9 - (k - len(path)) + 2): # 剪枝
currentSum += i # 处理
path.append(i) # 处理
self.backtracking(targetSum, k, currentSum, i + 1, path, result) # 注意i+1调整startIndex
currentSum -= i # 回溯
path.pop() # 回溯