剪枝优化,这里剪枝优化的关键点在于,剩下还需要选d个数,倒着选,剩下选择的数的范围是[1, i],如果 i + (i - 1) + (i - 2)… + (i - d + 1) = (2 * i - d + 1) / 2,等差数列和公式,即最大的d个数,的和加起来都没有,再加上之前选择的数的值的和都达不到目标值,就可以不继续往下递归;
代码:
class Solution {
public:
vector<vector<int>> combinationSum3(int k, int n) {
vector<vector<int>> ans;
vector<int> path;
auto dfs = [&](auto&& dfs, int i, int t) {
int d = k - path.size(); // 还要选 d 个数
if (t < 0 || t > (i * 2 - d + 1) * d / 2) { // 剪枝优化
return;
}
// 这是t 只能是 >= 0, d >= 0
if (d == 0) { // 找到一个合法组合
ans.emplace_back(path);
return;
}
for (int j = i; j >= d; j--) {
path.push_back(j);
dfs(dfs, j - 1, t - j);
path.pop_back();
}
};
dfs(dfs, 9, n);
return ans;
}
};