【如果笔记对你有帮助,欢迎关注&点赞&收藏,收到正反馈会加快更新!谢谢支持!】
参考:1. 回溯算法套路②组合型回溯+剪枝【基础算法精讲 15】_哔哩哔哩_bilibili 2. https://www.youtube.com/watch?v=kyLxTdsT8ws&list=PLDN4rrl48XKpZkf03iYFl-O29szjTrs_O&index=65
ps:笔记和代码按本人理解整理,重思路
上期笔记
回溯算法学习笔记(一)子集型:电话号码的字母组合,子集,分割回文串-CSDN博客
题目1:组合
- 题意:返回范围
[1, n]
中所有可能的k
个数的组合 - 组合回溯过程(以 n = 4, k = 2举例)
- 代码:
class Solution: def combine(self, n: int, k: int) -> List[List[int]]: results = [] path = [] def backtracking(start, k): # k表示还要加多少数 if k == 0: # k为0说明组合已完成 results.append(path[:]) return for i in range(start, n+1): path.append(i) backtracking(i+1, k-1) # 新的start为i+1,加入一个数后k要-1 path.pop() # 回溯(恢复现场) backtracking(1, k) return results
题目2:组合总和III
- 题意:找出所有相加之和为
n
的k
个数的组合,只使用数字1到9,每个数字最多用一次 - 对比上题的变化:需要计算和,并且要满足和为k的条件才能把组合加进结果
- 代码:
from typing import List class Solution: def combinationSum3(self, k: int, n: int) -> List[List[int]]: results = [] path = [] # 记录组合 sum_ = 0 # 记录组合的和 def backtrack(start, k): nonlocal sum_ if k == 0 and sum_ == n: # 组合已满且满足和为0 results.append(path[:]) return elif k == 0: # 组合已满但不满足和为0 return for i in range(start, 10): # 数字范围是1到9 if i > n: # 已经不能满足和为n(剪枝) break path.append(i) sum_ += i backtrack(i+1, k-1) path.pop() # 回溯 sum_ -= i backtrack(1, k) return results
题目3:括号生成
- 变化:加到组合的只有左括号或者右括号
- 记录还可以加多少左括号和右括号
- 条件:
- 如果要加左括号:左括号未加满
- 如果要加右括号:当前组合里,左括号多于右括号
- 代码:
class Solution: def generateParenthesis(self, n: int) -> List[str]: left_brackets = 0 results = [] path = '' def backtracking(left_brackets, right_brackets): nonlocal path if left_brackets == 0 and right_brackets == 0: results.append(path[:]) return if left_brackets > 0: # 可加左括号 path += '(' backtracking(left_brackets-1, right_brackets) path = path[:-1] if right_brackets > left_brackets: # 可加右括号 path += ')' backtracking(left_brackets, right_brackets-1) path = path[:-1] backtracking(n, n) return results