parent
f572d2c9e0
commit
0d6a3a7513
14
include/s0040_combination_sum_ii.hpp
Normal file
14
include/s0040_combination_sum_ii.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef S0040_COMBINATION_SUM_II_HPP
|
||||
#define S0040_COMBINATION_SUM_II_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class S0040 {
|
||||
public:
|
||||
vector<vector<int>> combinationSum2(vector<int>& candidates, int target);
|
||||
};
|
||||
|
||||
#endif
|
@ -69,6 +69,31 @@ void combineDFS(int n, int k, int begin, vector<int> &path,
|
||||
}
|
||||
```
|
||||
|
||||
## [216. 组合总和 III](https://leetcode.cn/problems/combination-sum-iii/)
|
||||
|
||||
## [39. 组合总和](https://leetcode.cn/problems/combination-sum/)
|
||||
|
||||
## [216. 组合总和 III](https://leetcode.cn/problems/combination-sum-iii/)
|
||||
## [40. 组合总和 II](https://leetcode.cn/problems/combination-sum-ii/)
|
||||
|
||||
最难的一个组合总和,因为 `candidates` 有重复元素,而要求最终结果不能重复。
|
||||
|
||||
e.g. 1
|
||||
|
||||
```text
|
||||
Input: candidates = [10,1,2,7,6,1,5], target = 8
|
||||
Output:
|
||||
[
|
||||
[1,1,6],
|
||||
[1,2,5],
|
||||
[1,7],
|
||||
[2,6]
|
||||
]
|
||||
```
|
||||
|
||||
如果你只是单纯地在 s0039 的基础上在下一次递归中将 `startIndex` 设为 `i + 1` 那么最终结果就会出现两个 `[1, 2, 5]`。
|
||||
|
||||
如果你直接排除 `candidates[i] == candidates[i - 1]` 的情形,那么最终结果就没有 `[1, 1, 6]`。
|
||||
|
||||
正确的逻辑应该是如果 `candidates[i] == candidates[i - 1]` 且 `candidates[i - 1]` 使用过,则剪枝。
|
||||
|
||||
怎么判断 `candidates[i - 1]` 是否使用过呢?我们创建一个 `vector<bool> used` 用来记录每个元素是否使用过。
|
||||
|
39
src/s0040_combination_sum_ii.cpp
Normal file
39
src/s0040_combination_sum_ii.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "s0040_combination_sum_ii.hpp"
|
||||
|
||||
void combinationSum2DFS(vector<int> &candidates, int target, int startIndex,
|
||||
vector<int> &path, int sum, vector<bool> &used,
|
||||
vector<vector<int>> &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();
|
||||
}
|
||||
}
|
||||
|
||||
vector<vector<int>> S0040::combinationSum2(vector<int> &candidates,
|
||||
int target) {
|
||||
// 对 candidates 进行升序排序,这是为了进行剪枝
|
||||
sort(candidates.begin(), candidates.end());
|
||||
// 初始化
|
||||
vector<int> path{};
|
||||
vector<vector<int>> result{};
|
||||
vector<bool> used(candidates.size(), false);
|
||||
combinationSum2DFS(candidates, target, 0, path, 0, used, result);
|
||||
return result;
|
||||
}
|
Loading…
Reference in New Issue
Block a user