• 模板

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     1 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
    23
     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
    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
    22
     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
    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
     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
    2
    3
    1 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
    33
     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;
    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 };
  • image-20230320174521477

    image-20230320174523124

    未优化版本:

    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
    class 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
    32
     1 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 };