代码随想录算法训练营Day24 | 回溯理论基础、77.组合

回溯理论基础

回溯和递归是相辅相成的,只要有递归就有回溯(执行完一次递归就自动回溯到上一层)

回溯的效率

回溯不是一个高效的算法,而是一个纯暴力的过程

有些问题没有更好的解法,只能使用暴力搜索,这时就可以使用回溯法。包括以下问题:

1、组合问题

2、切割问题

3、子集问题

4、排列问题

5、棋盘问题(N皇后、解数独等)

如何理解回溯法

回溯法解决的问题都可以抽象为树形结构(N叉树)

回溯法的模板

void backtracking( 参数 ){
    // 终止条件
    if( 终止条件 ){
          收集结果(通常在叶子节点收集结果)
          return;
    }

    // 单层逻辑(通常为一个for循环,每次循环都继续递归)
    for(集合元素集){
           // 处理节点的操作
           // 递归
           // 回溯(还原,撤销对节点的操作)
    }
}

回溯三部曲:

1、确定递归函数的参数与返回值:返回值一般是void

2、确定递归的终止条件

3、确定单层递归的逻辑

 77.组合

思考了挺久,最后按模板做出来了(开心)

剪枝操作挺难想明白的

回溯三部曲:

· 参数:

        vector<vector<int>> ans:存放最终结果的全局变量

        vector<int> cur:当前路径下的组合(也可以设置为全局变量)

        int num:当前已经完成搜索的值,本次递归中从num + 1开始搜索

        int& k,int& n:题意中的k与n

· 终止条件:组合中的元素个数等于k,说明完成组合,将结果进行保存并返回

· 单层逻辑:

        节点操作:当前组合(cur)中添加当前值(i)

        递归:i已经完成操作,传入i+1进行递归

        回溯:i在该位置的所有组合已经收集完成,将i弹出当前组合

· 剪枝条件:

        原循环终止条件:i <= n;

        剪枝后的终止条件: i <= n - (k - cur.size()) + 1

        剪枝条件即:n - i + 1 >= k - size

        · n - i + 1代表当前序列中还剩下的元素个数(+1代表包括了当前节点)
        · k - size代表组合中还需要几个元素
        · 所以整个剪枝的含义为:当前序列中剩余的元素需要大于等于组合中还缺的元素个数

vector<vector<int>> ans;

void backtracking(int num, int& k, int& n, vector<int> cur) {
	// 终止条件:数组长度为k
	if (cur.size() == k) {
		// 保存结果
		ans.push_back(cur);
		return;
	}

	for (int i = num + 1; i <= n - (k - cur.size()) + 1; ++i) {
		// 进行节点操作
		cur.push_back(i);
		// 递归
		backtracking(i, k, n, cur);
		// 还原节点操作(回溯)
		cur.pop_back();
	}
}

vector<vector<int>> combine(int n, int k) { 
	backtracking(0, k, n, {});
	return ans;
}

 

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值