leetcode刷题——回溯例题

文章目录

一、组合问题

77. 组合:n个数中求k个数的组合问题
在这里插入图片描述

  • 思路:每次从集合中选取元素,可选择的范围随着选择的进行而收缩,调整可选择的范围。终止条件:每次搜索到了叶子节点,我们就找到了一个结果。for循环用来横向遍历,递归的过程是纵向遍历。backtracking(递归函数)通过不断调用自己一直往深处遍历,总会遇到叶子节点,遇到了叶子节点就要返回。
  • 参数含义:

n:相当于树的宽度
k:相当于树的深度。
startIndex:这个参数用来记录本层递归的中,集合从哪里开始遍历(集合就是[1,…,n] )
len(path):已经选择的元素个数
k-len(path):还需要的元素个数

  • 剪枝优化:
    可以剪枝的地方就在递归中每一层的for循环所选择的起始位置。如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了。

for i in range(StartIndex, n-(k-len(path)) + 2): #
左闭右开,在集合n中至多要从该起始位置 : n - (k - len(path) + 1,开始遍历

在这里插入图片描述

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        res = []   # 存放符合条件结果的集合
        path = []  # 用来存放符合条件单一结果
        def backtrack(n, k, StartIndex):  # 回溯(递归)
            if len(path) == k:  # 终止条件
                res.append(path[:])  # 存放结果
                return
            for i in range(StartIndex, n-(k-len(path)) + 2):  # 左闭右开,在集合n中至多要从该起始位置 : n - (k - len(path) + 1,开始遍历
                path.append(i)  # 处理节点 
                backtrack(n, k, i+1)  # 递归:控制树的纵向遍历,注意下一层搜索要从i+1开始
                path.pop()  # 回溯,撤销处理的节点
        backtrack(n, k, 1)
        return res

216. 组合总和 III

  • 树的宽度为9,深度为k
  • 优化剪枝:(1)目前求得的和大于n,则剪枝(2)遍历时startindex至多遍历到9-(k-len(path))+1
  • 对于该层上的每个结点,都要进行以下步骤:处理节点–递归–回溯
class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        res=[]
        path=[]
        def backtrack(startindex,sum,n,k):
            if sum>n:return  # 剪枝
            if sum==n and len(path)==k:res.append(path[:])   # 终止条件:走到叶子结点且和为n
            for i in range(startindex,9-(k-len(path))+2):  # 宽度遍历
                # 处理结点
                path.append(i)
                sum+=i
                # 递归
                backtrack(i+1,sum,n,k)  # 深度遍历
                # 回溯
                path.pop()
                sum-=i
        backtrack(1,0,n,k)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值