题目描述
给你一个无重复元素的整数数组candidates和一个目标整数target,找出candidates中可以使数字和为目标数target的所有不同组合,并以列表形式返回。你可以按任意顺序返回这些组合。
candidates中的同一个 数字可以无限制重复被选取。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为target的不同组合数少于150个。
题目链接
https://leetcode-cn.com/problems/combination-sum/
复杂度
时间复杂度:
O(S):
其中S为所有可行解的长度之和。
O(n*2的n次方)是一个比较松的上界,因为n个位置每次考虑选或者不选,如果符合条件,就加入答案的时间代价。
但是实际运行的时候,因为不可能所有的解都满足条件,递归的时候还会使用target-candidates[idx]>=0进行剪枝,所以实际运行情况是远远小于上界。
空间复杂度:
O(target)
除了答案数组之外,空间复杂度取决于递归的栈深度,在最差的情况下需要递归O(target)层
示例
示例一:
输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。
示例二:
输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]
示例三:
输入: candidates = [2], target = 1
输出: []
说明
代码
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
List<Integer> combine = new ArrayList<Integer>();
dfs(candidates, ans, combine, target, 0);
return ans;
}
public void dfs(int[] candidates, List<List<Integer>> ans, List<Integer> combine, int target, int idx) {
if (idx == candidates.length) {
return;
}
if (target == 0) {
ans.add(new ArrayList<Integer>(combine));
return;
}
dfs(candidates, ans, combine, target, idx + 1);
if (target - candidates[idx] >= 0) {
combine.add(candidates[idx]);
dfs(candidates, ans, combine, target - candidates[idx], idx);
combine.remove(combine.size() - 1);
}
}
}