代码随想录算法训练营第二十四天 | 回溯算法 part 1 | 理论基础、77. 组合

理论

回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。

在这里插入图片描述

回溯的模板:

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

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

77. 组合

Leetcode

在这里插入图片描述

思路

在这里插入图片描述
图中可以发现n相当于树的宽度,k相当于树的深度。图中每次搜索到了叶子节点,我们就找到了一个结果。相当于只需要把达到叶子节点的结果收集起来,就可以求得 n个数中k个数的组合集合。

剪枝

对于该回溯算法,是可以进行剪枝优化的。

举个例子,如果n = 4,k = 4的话,那么第一层for循环的时候,从元素2开始的遍历都没有意义了。 在第二层for循环,从元素3开始的遍历都没有意义了。因为剩余元素的数量加起来也到不了4(k = 4)。

所以,可以剪枝的地方就在递归中每一层的for循环所选择的起始位置。

如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了。

代码

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        res = []
        path = []

        def helper(startIndex, n, k):
            if len(path) == k:
                res.append(path.copy())
                return

            for i in range(startIndex, n + 1):
                path.append(i)
                helper(i + 1, n, k)
                path.pop()

        helper(1, n, k)
        return res

剪枝优化

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        res = []
        path = []

        def helper(startIndex, n, k):
            if len(path) == k:
                res.append(path.copy())
                return

            for i in range(startIndex, n -(k-len(path)) + 2):
                path.append(i)
                helper(i + 1, n, k)
                path.pop()

        helper(1, n, k)
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值