题目描述:
给定一个无重复元素的数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的数字可以无限制重复被选取。
说明:
- 所有数字(包括
target
)都是正整数。 - 解集不能包含重复的组合。
示例 1:
1 | 输入:candidates = [2,3,6,7], target = 7, |
示例 2:
1 | 输入:candidates = [2,3,5], target = 8, |
提示:
- $1 <= candidates.length <= 30$
- $1 <= candidates[i] <= 200$
candidate
中的每个元素都是独一无二的。- $1 <= target <= 500$
链接:
https://leetcode-cn.com/problems/combination-sum
题目分析
题目要求所有的可行解,则依然可以使用回溯的方法来进行搜索遍历,也即对于每一个数 candidates[i]
,都可以选择是否将其加入结果中,然后再转化为搜索 target-candidates[i]
的问题。为了避免产生重复解,我们按照 candidates
的顺序添加,也即若当前选择不添加 candidates[i]
,则转化的子问题也不能再添加 candidates[i]
。注意到题目中的数字可以无限制重复选取,则我们每次都需要保持从上一次添加的数字开始(也即上一次添加的数字仍然可以添加)。每当 target
为 0,意味着当前添加的数字的和为 target
,也即找到了一组解,将其添加到结果列表中。
而为了加快搜索速度,我们可以进行剪枝。比如我们可以先对 candidates
进行排序,当 target
已经小于当前想添加的数字时,也肯定小于后面所有的数字,则都不会是结果,则可以直接跳出循环返回。
1 | class Solution { |
时间复杂度:$O(S)$,$S$ 是可行解的长度之和。我们遍历了所有的可行解得到结果,而对于不可行的情况马上剪枝,则时间复杂度是可行解的长度之和。因为这道题确实比较难给出一个较紧密的上界。对于每个数字选或者不选,一共拥有非常多的可能,这是指数级别的。但是我们进行的剪枝可以排除掉非常多的情况,因此实际的运行情况不好以target
的大小或者是 candidates
的大小界定。
空间复杂度:$O(target)$。作为结果返回的数组不计入所需空间中,而所有的数字都是正整数,则最大的可行解长度也就是 target
的值(全由 1 构成可行解),这也是我们栈递归的最大深度,因此空间复杂度为 $O(target)$。