回溯算法
模板
1
2
3
4
5
6
7
8
9
10
11
121 void backtracking(参数) {
2 if (终止条件) {
3 存放结果;
4 return;
5 }
6
7 for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
8 处理节点;
9 backtracking(路径,选择列表); // 递归
10 回溯,撤销处理结果;
11 }
12 }未优化版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
231 class Solution {
2 private:
3 vector<vector<int>> result; // 存放符合条件结果的集合
4 vector<int> path; // 用来存放符合条件结果
5 void backtracking(int n, int k, int startIndex) {
6 if (path.size() == k) {
7 result.push_back(path);
8 return;
9 }
10 for (int i = startIndex; i <= n; i++) {
11 path.push_back(i); // 处理节点
12 backtracking(n, k, i + 1); // 递归
13 path.pop_back(); // 回溯,撤销处理的节点
14 }
15 }
16 public:
17 vector<vector<int>> combine(int n, int k) {
18 result.clear(); // 可以不写
19 path.clear(); // 可以不写
20 backtracking(n, k, 1);
21 return result;
22 }
23 };剪枝优化版本:
1
1 for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
221 class Solution {
2 private:
3 vector<vector<int>> result;
4 vector<int> path;
5 void backtracking(int n, int k, int startIndex) {
6 if (path.size() == k) {
7 result.push_back(path);
8 return;
9 }
10 for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) { // 优化的地方
11 path.push_back(i); // 处理节点
12 backtracking(n, k, i + 1);
13 path.pop_back(); // 回溯,撤销处理的节点
14 }
15 }
16
17 public:
18 vector<vector<int>> combine(int n, int k) {
19 backtracking(n, k, 1);
20 return result;
21 }
22 };未优化版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
301 class Solution {
2 private:
3 vector<vector<int>> result; // 存放结果集
4 vector<int> path; // 符合条件的结果
5 // targetSum:目标和,也就是题目中的n。
6 // k:题目中要求k个数的集合。
7 // sum:已经收集的元素的总和,也就是path里元素的总和。
8 // startIndex:下一层for循环搜索的起始位置。
9 void backtracking(int targetSum, int k, int sum, int startIndex) {
10 if (path.size() == k) {
11 if (sum == targetSum) result.push_back(path);
12 return; // 如果path.size() == k 但sum != targetSum 直接返回
13 }
14 for (int i = startIndex; i <= 9; i++) {
15 sum += i; // 处理
16 path.push_back(i); // 处理
17 backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
18 sum -= i; // 回溯
19 path.pop_back(); // 回溯
20 }
21 }
22
23 public:
24 vector<vector<int>> combinationSum3(int k, int n) {
25 result.clear(); // 可以不加
26 path.clear(); // 可以不加
27 backtracking(n, k, 0, 1);
28 return result;
29 }
30 };剪枝优化版本:
1
2
31 if (sum > targetSum) { // 剪枝操作
2 return;
3 }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
331 class Solution {
2 private:
3 vector<vector<int>> result; // 存放结果集
4 vector<int> path; // 符合条件的结果
5 // targetSum:目标和,也就是题目中的n。
6 // k:题目中要求k个数的集合。
7 // sum:已经收集的元素的总和,也就是path里元素的总和。
8 // startIndex:下一层for循环搜索的起始位置。
9 void backtracking(int targetSum, int k, int sum, int startIndex) {
10 if (sum > targetSum) { // 剪枝操作
11 return;
12 }
13 if (path.size() == k) {
14 if (sum == targetSum) result.push_back(path);
15 return; // 如果path.size() == k 但sum != targetSum 直接返回
16 }
17 for (int i = startIndex; i <= 9; i++) {
18 sum += i; // 处理
19 path.push_back(i); // 处理
20 backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
21 sum -= i; // 回溯
22 path.pop_back(); // 回溯
23 }
24 }
25
26 public:
27 vector<vector<int>> combinationSum3(int k, int n) {
28 result.clear(); // 可以不加
29 path.clear(); // 可以不加
30 backtracking(n, k, 0, 1);
31 return result;
32 }
33 };未优化版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29class Solution {
private:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {
if (sum > target) {
return;
}
if (sum == target) {
result.push_back(path);
return;
}
for (int i = startIndex; i < candidates.size(); i++) {
sum += candidates[i];
path.push_back(candidates[i]);
backtracking(candidates, target, sum, i); // 不用i+1了,表示可以重复读取当前的数
sum -= candidates[i];
path.pop_back();
}
}
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
result.clear();
path.clear();
backtracking(candidates, target, 0, 0);
return result;
}
};剪枝优化版本:
1
1 for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
321 class Solution {
2 private:
3 vector<vector<int>> result;
4 vector<int> path;
5 void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {
6 if (sum > target) {
7 return;
8 }
9 if (sum == target) {
10 result.push_back(path);
11 return;
12 }
13
14 // 如果 sum + candidates[i] > target 就终止遍历
15 for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) {
16 sum += candidates[i];
17 path.push_back(candidates[i]);
18 backtracking(candidates, target, sum, i);
19 sum -= candidates[i];
20 path.pop_back();
21
22 }
23 }
24 public:
25 vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
26 result.clear();
27 path.clear();
28 sort(candidates.begin(), candidates.end()); // 需要排序
29 backtracking(candidates, target, 0, 0);
30 return result;
31 }
32 };
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 怀民亦未寝。!