给定一个无重复元素的数组 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]
]
解题思路:首先还是按照递归框架写出来。然后考虑递归结束的条件,想到递归结束跟递归参数设计有关系,idx如果扫描到数组外面会结束,但是我们想要的答案是target==0时的解,因此多了一次递归结束的判断,递归结束判断的时候解的拼凑从来不是重点。
因此重点放在递归上,那么递归部分怎么写,显然每到一个idx位置,都有两种选择,选和不选当前数字,但是idx要不要加一,因为可以重复选,因此还是可以在robot中放idx,然后就是要记录当前这个数字了,明显用path记录,为什么不用boolean数组记录,因为很麻烦,然后target为0,拼凑一下答案就行。
class Solution {
List<List<Integer>> ans=new ArrayList<>();
int [] path=new int[100];//记录答案
int len=0;
public void robot(int idx,int [] nums,int target){//idx是扫描到数组哪个数字
if(target==0){
//拼答案,把记录在path里的数字拿出来
List<Integer> res=new ArrayList<>();
for(int i=0;i<len;i++){
res.add(path[i]);
}
ans.add(res);
return;
}
if(target<0||idx>=nums.length)
return;
//写递归,两种策略取和不取nums[idx]
path[len]=nums[idx];
len++;
robot(idx,nums,target-nums[idx]);//取但是idx不加1,因为下一次还可以取这个数
len--;//必须加这行,因为递归结束后不满足条件的数要从刚加入的删除掉,也就是指针回滚
robot(idx+1,nums,target);//不在取前面的数
}
public List<List<Integer>> combinationSum(int[] candidates, int target) {
robot(0,candidates,target);
return ans;
}
}