代码随想录二刷 | 回溯 |组合总和
- 题目描述
- 解题思路
- 代码实现
题目描述
39.组合总和
给定一个无重复元素的数组 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] ]
解题思路
本题搜索的过程抽象成树形结构如下:
注意图中叶子节点的返回条件,因为本题没有组合数量要求,仅仅是总和的限制,所以递归没有层数的限制,只要选取的元素总和超过target,就返回!
回溯三部曲
-
递归函数的参数
定义两个全局变量,二维数组result存放结果集,数组path存放符合条件的结果。首先是题目中给出的参数,集合candidates, 和目标值target。
此外还需要定义int型的sum变量来统计单一结果path里的总和,startIndex来控制for循环的起始位置。
vector<vector<int>> result; vector<int> path; void backtracking(vector<int>& candidates, int target, int sum, int startIndex)
-
递归函数的终止条件
终止只有两种情况,sum大于target
和sum等于target
。sum等于target的时候,需要收集结果,代码如下:
if (sum > target) {return; } if (sum == target) {result.push_back(path);return; }
-
单层搜索的逻辑
单层for循环依然是从startIndex开始,搜索candidates集合。for (int i = startIndex; i < candidates.size(); i++) {sum += candidates[i];path.push_back(candidates[i]);// 关键点:不用i+1了,表示可以重复读取当前的数backtracking(candidates, target, sum, i); sum -= candidates[i]; // 回溯path.pop_back(); // 回溯 }
代码实现
class Solution {
private:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {if (sum > target) {return;}if (sum == target) {result.push_back(path);return;}for (int i = startIndex; i < candidates.size(); i++) {sum += candidates[i];path.push_back(candidates[i]);backtracking(candidates, target, sum, i); // 不用i+1了,表示可以重复读取当前的数sum -= candidates[i];path.pop_back();}}
public:vector<vector<int>> combinationSum(vector<int>& candidates, int target) {result.clear();path.clear();backtracking(candidates, target, 0, 0);return result;}
};