代码随想录 回溯算法 C++

对于回溯算法,我对于他的本质理解为穷举,当然,并不否认在过程中可以剪枝,使得时间复杂度下降,但是究其本质还是去考虑所有的情况

基本的格式如下(接下来的代码学习也会按照这个格式来写,从而不断加深印象)

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

例题1 . - 力扣(LeetCode)

//三部曲去考虑,边界条件,返回值与传递参数, 循环过程
//当然这其中把temp去作为一个参数也是可以的,但是会占用很多的栈空间,想要去试试的也可以自己写一写
class Solution {
private:
  vector<vector<int>> ans;
  vector<int> temp;
  void backtracking(int m, int n, int k){
    if(temp.size() == k){
      //边界条件
      ans.push_back(temp);
      return;
    }
    for(int i = m; i <= n; i++){
      temp.push_back(i);
      backtracking(i + 1, n, k);
      temp.pop_back();
    }
  }
public:
    vector<vector<int>> combine(int n, int k) {
      backtracking(1, n, k);
      return ans;
    }
};

剪枝优化在当中也被提及,可能在代码随想录的一开始描述的有一些模糊,我们用这个例子就可以了,n = 4,k = 4的情况,第一层的回溯按照原来的情况是1-4的循环,但是我们很清楚,只有一个可能性,那就是[1, 2, 3, 4]。所以i的限制条件可以变成 i <= n - (k - temp.size()) + 1。这样的话第一层就是4 - ( 4 - 0 ) + 1 = 1-------i <= 1就可以了。

例题2.. - 力扣(LeetCode)

//和第一题大差不差,把第一题提到的vector作为参数了。当然写起来也麻烦了许多
class Solution {
private:
    vector<vector<int>> ans;
    void backtracking(int k, int n, int start, vector<int> temp, int sum){
      if(sum == n && temp.size() == k) {
        ans.push_back(temp);
        return;
      }
      if(sum >= n || temp.size() >= k) return;
      for(int i = start; i < 10 && i <= n - sum + 1; i++){
        temp.push_back(i);
        backtracking(k, n, i + 1, temp, sum + i);
        temp.pop_back();
      }
    }
public:
    vector<vector<int>> combinationSum3(int k, int n) {
      backtracking(k, n, 1, {}, 0);
      return ans;
    }
};

例题3.. - 力扣(LeetCode)

class Solution {
//本质与例题1相似
private:
  vector<string> ans;
  vector<string> strs = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
  string s;
  void backtracking(string digits, int start){
    if(start == digits.length()){
      ans.push_back(s);
      return;
    }
    int num = digits[start] - '2';
    for(int i = 0; i < strs[num].length(); i++){
      s += strs[num][i];
      backtracking(digits, start + 1);
      s.pop_back();
    }
  }
public:
    vector<string> letterCombinations(string digits) {
      if(digits == "") return ans;
      backtracking(digits, 0);
      return ans;
    }
};

例题4.. - 力扣(LeetCode)

class Solution {
private:
  vector<vector<int>> ans;
  vector<int> path;
  void backtracking(vector<int> candidates, int target, int start){
    if(target == 0){
      ans.push_back(path);
      return;
    }
    if(target < 0) return;
    for(int i = start; i < candidates.size(); i++){
      path.push_back(candidates[i]);
      backtracking(candidates, target - candidates[i], i);
      path.pop_back();
    }
  }
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        backtracking(candidates, target, 0);
        return ans;
    }
};

代码随想录网址:代码随想录

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值