1 void backtracking(参数) { 2 if (终止条件) { 3 存放结果; 4 return; 5 } 6 7 for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 8 处理节点; 9 backtracking(路径,选择列表); // 递归 10 回溯,撤销处理结果; 11 } 12 }
1 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 for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置
1 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 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 if (sum > targetSum) { // 剪枝操作 2 return; 3 }
也就是:
1 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; // 如果path.size() == k 但sum != targetSum 直接返回 12 } 13 if (path.size() == k) { 14 if (sum == targetSum) result.push_back(path); 15 return; 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 };