回溯问题总结
回溯算法可以解决的问题大致分为以下几类:
- 组合问题
- 分割问题
- 子集问题
- 排列问题
- 棋盘问题
- 其它
组合问题
组合问题本身是不讲究顺序的,以下面这道题为例:

我们要选取的是k个组合,所以当path.size() == k
时,就可以把当前遍历路径添加到结果中。
class
public:
vector<vector<int>> result;
vector<int> path;
void backtrack(int startIndex, int n, int k) {
if(path.size() == k) {
result.push_back(path);
return;
}
//for循环是同一个树层的不同分叉
for(int i = startIndex; i <= n - (k - path.size()) + 1; i++) {
path.push_back(i);
//递归的过程是在同一个树杈上继续选择
backtrack(i + 1, n, k);
path.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
backtrack(1, n, k);
return result;
}
};

本题的关键是对于结果的去重。并且去重要求在同一层的不同树杈上进行去重
class
public:
vector<int> path;
vector<vector<int>> result;
int sum = 0;
void backtrack(vector<int>& candidates, int target, int startIndex) {
if(sum > target) return;
if(sum == target) {
result.push_back(path);
return;
}
for(int i = startIndex; i < candidates.size(); i++) {
if(i > startIndex && candidates[i] == candidates[i-1]) {
continue;
}
sum += candidates[i];
path.push_back(candidates[i]);
backtrack(candidates, target, i + 1);
path.pop_back();
sum -= candidates[i];
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
backtrack(candidates, target, 0);
return result;
}
};