回溯——组合总和
题目要求:
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个
这道题是经典的回溯算法应用题,核心思路是:通过递归遍历数组元素,每次选择一个数字加入组合,累加和,直到和等于目标值则记录组合;如果和超过目标值则回溯(撤销选择),继续尝试其他数字。
关键点
- 无重复元素,同一个数字可无限重复选取
- 组合去重:通过控制遍历起始索引避免重复组合(比如不回头选之前的数字)
- 回溯三要素:选择、递归、撤销选择
完整Java代码如下:
import java.util.ArrayList;
import java.util.List;
public class CombinationSum {
// 最终结果集合
List<List<Integer>> res = new ArrayList<>();
// 临时存储当前组合
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
// 回溯搜索,从索引0开始
backtrack(candidates, target, 0);
return res;
}
/**
* 回溯函数
* @param candidates 候选数组
* @param remain 剩余需要凑的目标值
* @param start 遍历起始索引(避免重复组合)
*/
private void backtrack(int[] candidates, int remain, int start) {
// 终止条件1:剩余值=0,找到有效组合,加入结果集
if (remain == 0) {
res.add(new ArrayList<>(path)); // 必须new,否则会被后续修改
return;
}
// 终止条件2:剩余值<0,组合无效,直接返回
if (remain < 0) {
return;
}
// 从start开始遍历,避免重复组合(不回头选之前的数)
for (int i = start; i < candidates.length; i++) {
// 1. 选择:将当前数字加入组合
path.add(candidates[i]);
// 2. 递归:继续从i开始(可重复选当前数),剩余值减去当前数
backtrack(candidates, remain - candidates[i], i);
// 3. 撤销选择:回溯,移除最后加入的数字
path.remove(path.size() - 1);
}
}
// 测试示例
public static void main(String[] args) {
CombinationSum solution = new CombinationSum();
// 示例1
int[] candidates1 = {2,3,6,7};
int target1 = 7;
System.out.println(solution.combinationSum(candidates1, target1));
// 输出:[[2,2,3],[7]]
// 示例2
int[] candidates2 = {2,3,5};
int target2 = 8;
System.out.println(solution.combinationSum(candidates2, target2));
// 输出:[[2,2,2,2],[2,3,3],[3,5]]
}
}
代码核心解释:
1. 回溯函数参数
- remain:剩余需要凑的目标值(每次选一个数就减去它,简化判断)
- start:遍历起始索引,保证不重复生成组合
比如选了2之后,只从2及之后的数字选,不会回头选3再选2,避免[2,3]和[3,2]重复
2. 核心逻辑
- 选择:把当前数字加入临时组合path
- 递归:继续从当前索引i递归(允许重复选当前数字),剩余值更新为remain-candidates[i]
- 回溯:递归结束后,移除path最后一个元素,尝试下一个数字
3. 终止条件
- remain = 0:组合和等于目标值,将path拷贝一份加入结果集
- remain < 0 组合和超过目标值,直接剪支,停止当前分支
浙公网安备 33010602011771号