给定一个无重复元素的数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的数字可以无限制重复被选取。
说明:
target
)都是正整数。示例 1:
输入: candidates =[2,3,6,7],
target =7
, 所求解集为: [ [7], [2,2,3] ]
示例 2:
输入: candidates = [2,3,5],
target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
这个题被自己点开过不知道多少次了,再不提交了它心里有些过不去。
嗯。。回溯算法,一直递归去求解,把所有组合都遍历一遍,将符合条件的加入到结果集中。
因为是可重复添加,每次遍历数组时都从数组的第一个数开始添加,当添加到货符合或不符合条件时,返回。可能会出现出现重复组合的情况比如[2,2,3],[2,3,2]这种,这是因为不管哪次都是从第一个数字开始遍历添加,增加一个变量,来控制从已经添加过的数字之后添加,嗯。。。说的很不清楚。。。。。。看看代码
for (int i = 0; i < candidates.length; i++) {
target -= candidates[i];
temp.add(candidates[i]);
help(result,temp,candidates,target);
temp.remove(temp.size()-1);
target += candidates[i];
}
上面这种写法是会出现重复结果的, 原因是因为i每回都从0开始取值,将它改一下改成下面的写法,即可,还要注意n++和n+1的区别,这是不一样的。
for (int i = n; i < candidates.length; i++) {
target -= candidates[i];
temp.add(candidates[i]);
help(result,temp,candidates,target,n++);
temp.remove(temp.size()-1);
target += candidates[i];
}
class Solution {
public List> combinationSum(int[] candidates, int target) {
List> result = new ArrayList<>();
List temp = new ArrayList<>();
help(result,temp,candidates,target,0);
return result;
}
public static void help(List>result, List temp, int[] candidates, int target,int n){
if (target == 0 ){
result.add(new ArrayList<>(temp));
return;
}
if (target < 0) {
return;
}
for (int i = n; i < candidates.length; i++) {
target -= candidates[i];
temp.add(candidates[i]);
help(result,temp,candidates,target,n++);
temp.remove(temp.size()-1);
target += candidates[i];
}
}
}