1 回溯法(排序+first索引+跳过重复元素+右分支收紧)
结合问题性质,基于回溯模板额外添加的主要步骤如下
- 排序使重复元素相邻
first
索引剪枝左分支不同序重复解- 跳过重复元素(两者相同且
nums[i-1]
用过则nums[i]
不再用) - 右分支收紧(
candidates[i] + sum > target
)
class Solution {
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;
// 4.first辅助跳过重复元素,两者相同且nums[i-1]用过则nums[i]不再用, 需结合[2]inPath实现
if (i > first && candidates[i] == candidates[i-1]) continue;
path.emplace_back(candidates[i]);
backtrack(candidates, target, sum + candidates[i], i + 1);
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
size = candidates.size();
// 1.升序排序
sort(candidates.begin(), candidates.end());
backtrack(candidates, target, 0, 0);
return solution;
}
};
可见,确实省内存了