随想录训练营21/60 | 回溯理论基础;LC 77. 组合

随想录训练营21/60 | 回溯理论基础;LC 77. 组合

回溯理论基础

什么时回溯?
之前学习了二叉树的知识,遍历二叉树时,一般用递归法,在计算和深度高度相关的题时也用到了回溯。回到父节点走其它孩子节点
回溯即递归,有递归就可以有回溯。回溯的本质是穷举,穷举所有可能,不是一个高效的算法。为什么还要学习回溯呢?
为什么回溯?
即使回溯效率低,但有些问题只能通过穷举法解决,如:组合问题;切割问题;子集问题;排列问题;棋盘问题。
如何理解回溯?
回溯法解决的问题都可以抽象为树形结构,以上问题本质都是在集合中找符合规则的子集,集合的大小就是树的宽度,递归的深度就是树的深度。
回溯的模板
与之前学习的三部曲相同:
先确定递归的返回值和参数;回溯一般没有返回值(void),参数比二叉树难,一般是根据递归逻辑确定参数
然后确定递归的终止条件;找到满足条件的自己就保存结果并返回
最后进行单层的递归逻辑;在集合中递归搜索,集合的大小就是孩子的多少。
伪代码:

void backtracking(param){
	if(终止条件){
		//存放结果;
		return;
	}	
	for(选择本层集合中的元素){
		处理节点;
		backtracking(param);//递归
		回溯;//有时候回溯操作不明显,隐含在递归操作中
	}
}

LC 77. 组合

题目链接LC 77. 组合
思路:递归的输入为剩余的集合,当满足终止条件就保存结果。思路不难,不要求顺序,也就是不能重复。
代码

class Solution {
public:
    
    //递归函数
    //set是集合,cur是当前的组合
    vector<vector<int>> result;
    void backtracking(vector<int> set, vector<int>cur, int k){
        //当组合的大小等于要求时,就保存并返回
        if(cur.size()==k){
            result.push_back(cur);
            return;
        }
        //不满足就进行递归,遍历传入的集合,注意之前处理过的节点之后就不能处理了
        for(int i=0; i<set.size();i++){
            cur.push_back(set[i]);
            vector<int> lastSet(set.begin()+i+1,set.end());
            backtracking(lastSet, cur, k);
            cur.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
        vector<int> set;
        for(int i=1; i<=n; ++i){
            set.push_back(i);
        }
        vector<int> cur;
        backtracking(set, cur, k);
        return result;
    }
    //--------上面的内存消耗太高,递归可以只传开始的--------
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(int begin, int n, int k){
        if(path.size()==k){//当路径长度到达k就可以保存结果
            result.push_back(path);
            return;
        }
        //当没有到达指定长度时
        for(int i=begin; i<=n; i++){
            path.push_back(i);//将begin放到path中,然后进行递归
            backtracking(i+1, n, k);
            path.pop_back();//回溯
        }
    }
    vector<vector<int>> combine(int n, int k) {
        backtracking(1, n, k);
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值