diff --git a/notes/src/backtrack.md b/notes/src/backtrack.md index 64005ab..5713b5f 100644 --- a/notes/src/backtrack.md +++ b/notes/src/backtrack.md @@ -23,7 +23,7 @@ void backtrack(NodeState &node, vector &result, int para1, int para2, // 终止条件 // 回溯法中的每个节点并不是真的树状节点,没有 `nullptr` ,因此用空指针来判断是否到了叶子结点并不合理,需要其它的一些方法来确定是否到达叶子节点,比如高度。 if (/* end condition */) { - result.push_back(node); + /* update result */ return; } @@ -51,6 +51,10 @@ void backtrack(NodeState &node, vector &result, int para1, int para2, } ``` +回溯法的一个很重要的考点在于如何去重。去重有两种思路,一个是用哈希表记录每一层的使用情况,另一种是排序 + 判断,后者性能更好所以优先选择后者。 + +具体算法参考 [40. 组合总和 II](./combinations.html) 和 [491. 递增子序列](./subsets.html) + 复杂度分析: - 时间复杂度:最长路径长度 × 搜索树的节点数 diff --git a/notes/src/combinations.md b/notes/src/combinations.md index 000c752..3f5c017 100644 --- a/notes/src/combinations.md +++ b/notes/src/combinations.md @@ -129,3 +129,33 @@ if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) // 对 candidates 进行升序排序,这是为了进行剪枝 sort(candidates.begin(), candidates.end()); ``` + +完整代码如下: + +```cpp +void combinationSum2DFS(vector &candidates, int target, int startIndex, + vector &path, int sum, vector &used, + vector> &result) { + // 结束条件:总和等于 target 。不存在总和大于 target 的情况,因为已经被剪枝了 + if (sum == target) { + result.push_back(path); + return; + } + + // 开始迭代 + int size = candidates.size(); + for (int i = startIndex; i < size; ++i) { + // 剪枝,当现在节点的 sum 已经超过了 target,就没必要继续迭代了 + if (sum + candidates[i] > target) break; + // 剪枝,但保留树枝重复的情况 + if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) + continue; + path.push_back(candidates[i]); + used[i] = true; + combinationSum2DFS(candidates, target, i + 1, path, sum + candidates[i], + used, result); + used[i] = false; + path.pop_back(); + } +} +``` diff --git a/notes/src/permute.md b/notes/src/permute.md index aeeadab..9d8a100 100644 --- a/notes/src/permute.md +++ b/notes/src/permute.md @@ -6,7 +6,7 @@ ## [47. 全排列 II](https://leetcode.cn/problems/permutations-ii/) -和 s0046 相比就加了去重。有两种去重思路,一个是用哈希表记录每一层的使用情况。另一种是排序 + 判断,后者性能更好所以优先选择后者。 +和 s0046 相比就加了去重。有两种去重思路,一个是用哈希表记录每一层的使用情况,另一种是排序 + 判断,后者性能更好所以优先选择后者。 哈希表法: