597 字
3 分钟
代码随想录算法训练营第十九天 | 回溯算法 Part01
回溯算法
回溯是一种在决策树中搜索所有可能路径的算法,用于解决组合、排列、子集等问题。
回溯三问
站在回溯树的一个节点上,需要思考三个核心问题:
- 路径:已经做出的选择。
- 选择列表:当前可以做的选择。
- 结束条件:到达决策树底层,无法再继续选择。
通用代码模板
result = []
def backtrack(路径, 选择列表): if 满足结束条件: result.append(路径[:]) return
for 选择 in 选择列表: 做选择 backtrack(路径, 选择列表) 撤销选择
🔁 核心:for 循环里递归调用,递归前“做选择”,递归后“撤销选择”。
组合问题
- 从一个集合中选出若干元素的所有组合。
- 无需考虑元素顺序。
- 回溯中通常通过控制递归的起始位置避免重复。
77. 组合
class Solution: def combine(self, n: int, k: int) -> List[List[int]]: self.res = [] # 存放结果 self.path = [] # 当前组合路径 self.backtrack(n, k, 1) return self.res
def backtrack(self, n, k, start): # 终止条件:组合长度为 k if len(self.path) == k: self.res.append(self.path[:]) return # 枚举所有可选数值 for i in range(start, n + 1): self.path.append(i) # 做选择 self.backtrack(n, k, i + 1) # 递归 self.path.pop() # 撤销选择
216. 组合总和 III
class Solution: def combinationSum3(self, k: int, n: int) -> List[List[int]]: self.path = [] # 当前路径 self.res = [] # 最终结果 self.sum = 0 # 当前路径和 self.backtrack(k, n, 1) return self.res
def backtrack(self, k, n, start): # 终止条件:长度为 k 且和为 n if len(self.path) == k and self.sum == n: self.res.append(self.path[:]) return # 剪枝:长度超了或者和超了 if len(self.path) >= k or self.sum > n: return for i in range(start, 10): # 数字范围 1~9 if i + self.sum > n: # 剪枝:当前值已超 break self.sum += i self.path.append(i) self.backtrack(k, n, i + 1) self.sum -= i self.path.pop()
17. 电话号码的字母组合
class Solution: # 数字到字符的映射 mapping = [ "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" ]
def letterCombinations(self, digits: str) -> List[str]: self.path = [] # 当前路径 self.res = [] # 存放所有结果 if not digits: return self.res self.backtrack(digits, 0) return self.res
def backtrack(self, digits, index): # 终止条件:路径长度等于输入数字长度 if len(self.path) == len(digits): self.res.append(''.join(self.path)) return
digit = ord(digits[index]) - ord('0') for char in self.mapping[digit]: self.path.append(char) # 做选择 self.backtrack(digits, index + 1) # 递归 self.path.pop() # 撤销选择
代码随想录算法训练营第十九天 | 回溯算法 Part01
https://fuwari.vercel.app/posts/code_musings_day_nineteen/