

cpp
class Solution {
private:
vector<vector<int>> result; // 存储所有符合条件的组合
vector<int> path; // 当前搜索路径(当前组合)
// 回溯函数
// candidates: 候选数字数组
// target: 目标总和
// sum: 当前路径中数字的总和
// startIndex: 当前搜索开始位置(防止重复组合)
void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {
// 终止条件1:当前和已经超过目标值
if (sum > target) {
return; // 直接返回,不再继续搜索
}
// 终止条件2:当前和等于目标值
if (sum == target) {
result.push_back(path); // 找到有效组合,加入结果集
return; // 返回上一层
}
// 从startIndex开始遍历候选数字
for (int i = startIndex; i < candidates.size(); i++) {
sum += candidates[i]; // 选择当前数字,更新总和
path.push_back(candidates[i]); // 将当前数字加入路径
// 递归调用,注意这里传的是 i 而不是 i+1
// 因为允许重复使用同一个数字
backtracking(candidates, target, sum, i);
// 回溯:撤销选择
sum -= candidates[i]; // 从总和中减去当前数字
path.pop_back(); // 从路径中移除当前数字
}
}
public:
// 主函数:组合总和
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
result.clear(); // 清空结果集
path.clear(); // 清空当前路径
// 从第0个位置开始回溯搜索
backtracking(candidates, target, 0, 0);
return result; // 返回所有符合条件的组合
}
};
例子 :candidates = [2,3,6,7], target = 7
初始状态:
result = [] path = [] sum = 0 startIndex = 0
第一层递归:backtracking([2,3,6,7], 7, 0, 0)
cppfor (int i = startIndex; i < candidates.size(); i++) { sum += candidates[i]; path.push_back(candidates[i]); backtracking(candidates, target, sum, i); // 不用i+1了,表示可以重复读取当前的数
不满足前面if条件 for循环,开始 i=0 sum = sum + candidates[0] = 0 + 2 = 2 path = [2] 进入递归...backtrackint([2,3,6,7], 7, 2, 0)
第二层递归:backtracking([2,3,6,7], 7, 2, 0)
不满足前面if条件 for循环,开始 i=0 sum = sum + candidates[0] = 2 + 2 = 4 path = [2,2] 进入递归...backtracking([2,3,6,7], 7, 4, 0)
第三层递归:backtracking([2,3,6,7], 7, 4, 0)
for循环,开始 i=0 sum = sum + candidates[0] = 4 + 2 = 6 path = [2,2,2] 进入递归...backtracking([2,3,6,7], 7, 6, 0)
第四层递归:backtracking([2,3,6,7], 7, 6, 0)
for循环,开始 i=0
cppfor (int i = startIndex; i < candidates.size(); i++) { sum += candidates[i]; path.push_back(candidates[i]); backtracking(candidates, target, sum, i); // 不用i+1了,表示可以重复读取当前的数
// 选择 candidates[0] = 2 sum += candidates[i]; // sum = 6 + 2 = 8 path.push_back(candidates[i]); // path = [2,2,2,2] backtracking(candidates, target, sum, i); // 参数:candidates=[2,3,6,7], target=7, sum=8, i=0
进入第五层递归(由于 sum=8 > target=7)
void backtracking(vector<int>& candidates, int target, int sum, int startIndex) { if (sum > target) { // 8 > 7? true return; // 立即返回 } // ... 不会执行后续代码 }
回溯(撤销选择)
// 返回到第四层递归,继续执行 sum -= candidates[i]; // sum = 8 - 2 = 6 path.pop_back(); // path = [2,2,2] // 循环继续...
for循环,开始 i=1
cppfor (int i = startIndex; i < candidates.size(); i++) { sum += candidates[i]; path.push_back(candidates[i]); backtracking(candidates, target, sum, i); // 不用i+1了,表示可以重复读取当前的数
// 选择 candidates[1] = 3 sum += candidates[i]; // sum = 6 + 3 = 9 path.push_back(candidates[i]); // path = [2,2,2,3] backtracking(candidates, target, sum, i); // 参数:candidates=[2,3,6,7], target=7, sum=9, i=0
.........
.........
.........