题目描述
给定一个无重复元素的数组 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]
]
解法思路
本题使用回溯算法来解决,先将数组进行排序,然后按照一定的规则依次遍历每个数。
具体做法如下:
- 定义一个结果数组
res、路径数组path和当前位置start。 - 如果当前路径
path中的数字和等于目标值target,那么将当前路径path加入到结果数组res中。 - 如果当前路径
path中的数字和已经大于目标值target,那么直接返回。 - 从当前位置
start开始向后遍历数组candidates,对于每个数,将其加入到路径path中。 - 然后递归调用函数本身,但是此时的目标和应该减去当前遍历到的数
candidates[i]。 - 递归结束后,将路径
path中的最后一个数弹出,回溯到上一层继续寻找其他可能性。
代码实现
function combinationSum(candidates: number[], target: number): number[][] {
const res: number[][] = [];
const path: number[] = [];
candidates.sort((a, b) => a - b);
const dfs = (start: number, target: number) => {
if (target === 0) {
res.push([...path]);
return;
}
for (let i = start; i < candidates.length && target >= candidates[i]; i++) {
path.push(candidates[i]);
dfs(i, target - candidates[i]);
path.pop();
}
};
dfs(0, target);
return res;
}
复杂度分析
时间复杂度为 O(n^(target/min(candidates))),其中 n 为候选数组 candidates 的长度。因为每个数字可以无限制重复被选取,所以搜索树的深度可以达到 target/min(candidates) 层。
空间复杂度为 O(target/min(candidates)),因为需要存储的路径的长度不会超过 target/min(candidates)。