Leetcode 组合总和 III
回溯法
java solution
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
//先创建返回的结果
List<List<Integer>> result = new ArrayList<>();
//然后开始回溯
backtrack(k, n, 1, new ArrayList<>(), result);
//返回结果
return result;
}
private void backtrack(int k, int remain, int start, List<Integer> path, List<List<Integer>> result) {
//首先判断是否满足条件,如果剩余和等于0且当前组合的长度为k, 添加当前path到result中,然后返回
if(path.size() == k && remain == 0) {
result.add(new ArrayList<>(path));
return;
}
//然后进行剪枝, 组合长度超过k 或者 remain < 0 时需要剪枝
if(path.size() > k || remain < 0) return;
//回溯
for(int i = start; i <= 9; i++) {
path.add(i);
//添加之后进行回溯判断
backtrack(k, remain - i, i + 1, path, result);
path.remove(path.size() - 1);
}
}
}
一个通用的回溯模板:
✅ 回溯算法的经典模板(Backtracking Template)
void backtrack(参数...) {
if (满足合法解的条件) {
// 处理合法结果(加入答案列表等)
return;
}
if (触发剪枝条件) {
// 过早结束(比如路径过长、和超了等)
return;
}
for (int i = 起始位置; i <= 边界; i++) {
// 做选择
路径.add(i);
// 递归,进入下一层决策树
backtrack(...);
// 撤销选择(回溯)
路径.remove(路径.size() - 1);
}
}
🧠 关键步骤详解:
① 判断合法结果:
if (路径.size() == k && remain == 0)
这个时候你已经找到了一个完整的结果,可以加入答案。
② 剪枝条件(终止非法路径):
if (路径.size() > k || remain < 0)
当路径已经无效(长度超了或者和超了),就不需要继续递归了,直接 return。
③ 遍历所有可能选项:
for (int i = start; i <= 9; i++)
依次尝试选取每一个可能的数字。
④ 做选择:
path.add(i)
当前这个数加入路径。
⑤ 回溯递归:
backtrack(...)
进入下一层决策树。
⑥ 撤销选择(回溯):
path.remove(path.size() - 1)
关键操作:撤回上一次的选择,回到上一步的状态,尝试新的可能。
✅ 常见题目都能用这个套路,比如:
- 组合问题(如本题)
- 排列问题(比如 Leetcode 46/47)
- 子集问题
- 数独、N皇后、迷宫路径
- 分割字符串、括号生成…