39. 组合总和
- 思路:本题要求的结果没有元素个数限制,且可以重复使用同一元素。抽象成树形结构如图:
- 从前面的组合题目中我们知道,集合的大小决定了树的宽度,递归的深度决定构成的树的深度。
- 回溯三部曲:
- 函数参数:集合candidates, 和目标值target,以及startIndex,用来记录本层递归的中,集合从哪里开始遍历,可以防止出现重复的组合。
- 终止条件:当当前收集到的元素和sum大于target时,结束递归;当sum等于target时,收集结果。
- 单层逻辑:单层for循环依然是从startIndex开始,搜索candidates集合。由于本题可以重复取同一个元素,所以在递归时,传入的startIndex参数不再是 i+1 而是 i 。
- 补充:对于组合问题,什么时候需要startIndex呢?
- 如果是一个集合来求组合的话,就需要startIndex,eg.77.组合,216.组合总和3
- 如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,eg.17.电话号码的数字组合
- 剪枝:如果已经知道下一层的sum会大于target,就没有必要进入下一层递归了。对总集合排序之后,如果下一层的sum(就是本层的 sum + candidates[i])已经大于target,就可以结束本轮for循环的遍历。
![](https://i-blog.csdnimg.cn/blog_migrate/07bc5348750fac750a1274b1df296fba.png)
- 时间复杂度: O(n * 2^n)
- 空间复杂度: O(target)
class Solution {
private:
vector<int> path;
vector<vector<int>&g