1 回溯法(sort first索引左收紧 右收紧)
遇到这类回溯问题,先不要慌,而是要根据题目要求快速在稿纸上画出基本case的决策树,回溯框架都是一样的,只是在此基础上依据问题进行修改就轻松很多了
结合本问题的输入和条件,我们对照上表可以得到如下思路
- 排序(使重复元素相邻)
first
索引左分支收紧(比如有了[2,2,3]
就不能有[2,3,2]
,即第1
个3
后面的元素必然≥3
)
完成以上两点可以保证AC,但还可以继续剪枝
candidates[i] sum > target
的分支不予考虑(右分支收紧)
class Solution {
private:
int size;
vector<vector<int>> solution;
vector<int> path;
public:
void backtrack(vector<int>& candidates, int target, int sum, int first) {
if (sum == target) {
solution.emplace_back(path);
return;
}
// 2.使用first索引收紧决策树起始分支(从左收紧)
for (int i = first; i < size; i ) {
// 3.收紧决策树终止分支(从右收紧)
if (candidates[i] sum > target) break;
path.emplace_back(candidates[i]);
backtrack(candidates, target, sum candidates[i], i);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
size = candidates.size();
// 1.升序排序(使重复元素相邻)
sort(candidates.begin(), candidates.end());
backtrack(candidates, target, 0, 0);
return solution;
}
};
注意:这里传入first
的参数是i
不是i 1
,因为题目说同一元素可以无限重复累加,所以决策树下一层的最左侧分支依然可以是上一层的第i
个分支
backtrack(candidates, target, sum candidates[i], i);
致谢
图片来源「代码随想录」公众号,欢迎大家关注这位大佬的公号