组合总和
题目来源于leetcode,解法和思路仅代表个人观点。传送门。
难度:中等
用时:大概20min
题目
给定一个无重复元素的数组 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]
]
提示:
1 <= candidates.length <= 30 1 <= candidates[i] <= 200 candidate
中的每个元素都是独一无二的。 1 <= target <= 500
思路
目标为target的组合 = 目标为target - candidates[i]的组合 + candidates[i]
如何找出不重复的组合?
设置一个candidates[i]的i起点位index,这次寻找,不能往前找。只能找当前位,以及后面的candidates
代码
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> ans = new ArrayList<>();
ans = dfs(candidates,target,0);
return ans;
}
public List<List<Integer>> dfs(int[] candidates,int target,int index){
List<List<Integer>> ans = new ArrayList<>();
for(int i=index;i<candidates.length;i++){
List<List<Integer>> result = new ArrayList<>();
//递归结束条件
if(target - candidates[i] == 0){
List<Integer> list = new ArrayList<>();
list.add(candidates[i]);
result.add(list);
}else if(target - candidates[i] < 0){
//什么都不做
}else{
//target - candidates[i] > 0
result = dfs(candidates,target - candidates[i],i);
//把当前数,加入到集合中
for(int j=0;j<result.size();j++){
result.get(j).add(candidates[i]);
}
}
//把target - candidates[i] < 0 的结果排除,不然会加入一个空数组
if(result.size()>=1)
ans.addAll(result);
}
return ans;
}
}
算法复杂度
时间复杂度: 时间复杂度:O(S),其中 S 为所有可行解的长度之和。
空间复杂度: O(target)。除答案数组外,空间复杂度取决于递归的栈深度,在最差情况下需要递归 O(target) 层。