数字可以无限选择。
来自图解面试算法, 动画来自吴师兄。
要求得出所有和为目标值的组合,那么这样使用回溯法将所有结果遍历一边是非常合适的。
数组中所有元素都是可以重复使用的,那么也就是说每次都可以从第一位开始,但是最终结果中不允许包括重复的组合,那么应该怎样解决呢,那就要将每组数据的第一个值的索引传递进去,每一次都是从这个位置开始判断,那么就可以避免将之前的元素重复使用了。
List<List<Integer>> result = new ArrayList<>(); // 最终结果
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
for (int i = 0; i < candidates.length; i++) {
ArrayList<Integer> resultList= new ArrayList<>(); // 其中一个可能的结果,如果符合则放入result
resultList.add(candidates[i]);
dfs(candidates, target, candidates[i], resultList, i);
}
return result;
}
private void dfs(int[] candidates, int target, int val, List<Integer> r, int j){ // val是candidates[i], r是resultList,j是i
// 递归base case:1. 找到target,将r放入结果
// 2. val大于结果,则退出
if (target==val){
result.add(new ArrayList<>(r));
return;
}
if (val>target){
return;
}
// 递归
for (int i = j; i < candidates.length; i++) { // 从当前位置开始循环
r.add(candidates[i]); // r先添加了当前的数
val+=candidates[i]; // val代表当前数组总和,更新val
dfs(candidates,target,val,r,i); // 用更新的val和i进行递归
//回溯
r.remove(r.size() - 1); // remove的参数可以是index,也可以是值,这里r.size-1的类型是int,不是Integer,即索引
// 即删除最后一个数字,因为加得过了
val-=candidates[i];
}
}