2024/5/1【回溯1/6】--代码随想录算法训练营day24|理论基础 、77. 组合

理论基础

是什么? 回溯函数也就是递归函数,指的都是一个函数。

本质上模拟的是嵌套for循环,递归是嵌套for循环,递归深度,代表嵌套负循环的次数

能解决什么问题?

在这里插入图片描述

组合问题【无序】:N个数里面按一定规则找出k个数的集合
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
排列问题【有序】:N个数按一定规则全排列,有几种排列方式
棋盘问题:N皇后,解数独等等

如何理解回溯法?—》抽象成“树形结构”

回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度就构成了树的深度。递归就要有终止条件,所以必然是一棵高度有限的树(N叉树)。

回溯模版

void backtracking(参数){
	if (终止条件):
		{收集结果;
		 return}
 		
	for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) : #处理集合的每一个元素
		{处理节点;
		 backtracking(路径,选择列表); #递归函数
		 回溯操作; #撤销处理节点的
		}
}

77. 组合

力扣链接
在这里插入图片描述

如果是暴力解法,k是递归深度,同时也是for循环嵌套数

for (int i = 1; i <= n; i++) {
    for (int j = i + 1; j <= n; j++) {
        cout << i << " " << j << endl;
    }
}

回溯三步曲
1.递归函数的参数和返回值 : 返回值void ,参数【n, k, startindex,路径path, 总结果result】startIndex 就是防止出现重复的组合
2.终止条件【到叶子结点,得到路径的长度是k,即为len(path) = k,收集结果result.append(path); return 】
3.单层递归的逻辑
在这里插入图片描述

未剪枝优化
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        result = []  # 存放结果集
        self.backtracking(n, k, 1, [], result)
        return result
    def backtracking(self, n, k, startIndex, path, result):
        if len(path) == k:
            result.append(path[:])
            return
        for i in range(startIndex, n + 1):  # 需要优化的地方
            path.append(i)  # 处理节点
            self.backtracking(n, k, i + 1, path, result)
            path.pop()  # 回溯,撤销处理的节点
剪枝优化
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        result = []  # 存放结果集
        self.backtracking(n, k, 1, [], result)
        return result
    def backtracking(self, n, k, startIndex, path, result):
        if len(path) == k:
            result.append(path[:])
            return
        for i in range(startIndex, n - (k - len(path)) + 2):  # 优化的地方,因为index从1开始 
            path.append(i)  # 处理节点
            self.backtracking(n, k, i + 1, path, result)
            path.pop()  # 回溯,撤销处理的节点

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值