【LeetCode77】组合

题目描述

给定区间 [1, n] 和一个整数 k,需要返回所有可能的 k 个数的组合。

思路

  1. 算法选择:回溯算法
    回溯算法是一种试探性搜索方法,非常适合用来解决组合问题。基本思想是:
    • 从数字 1 开始,逐步构建组合。
    • 当当前组合的长度等于 k 时,将该组合加入结果集。
    • 否则,继续尝试添加后续的数字。
    • 在尝试过程中,每一步都“做出选择”并递归,递归返回后撤销该选择(即“回溯”),从而探索其他可能的组合。
  2. 剪枝优化
    为了提高效率,可以在遍历时进行剪枝:
    • 如果当前已选数字个数加上剩余可选数字总数仍然不足以达到 k,则可以直接退出循环,避免不必要的递归调用。

代码

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

        # param path: 当前已经选择的数字组合
        def backtrack(start: int, path: List):
            if len(path) == k:
                res.append(path.copy())
            for i in range(start, n + 1): # 遍历从 start 到 n 的所有数字,注意区间的开闭
                # 剪枝:如果剩余数字数量不足以填满组合,则直接退出
                if len(path) + (n - i + 1) < k:
                    break
                 # 选择当前数字 i,加到当前组合中
                path.append(i)
                # 递归调用,从下一个数字开始继续选择
                backtrack(i + 1, path)
                # 回溯:撤销选择,将数字 i 从当前组合中删除
                path.pop()
        backtrack(1, [])
        return res

总结

  1. 回溯算法核心思想

    • 递归构造:用一个递归函数 backtrack 来构造组合,每次递归选择一个数字加入到当前组合 path 中。
    • 结束条件:当 path 的长度等于 k 时,将当前组合复制后加入结果集 res,然后结束当前递归分支。
    • 回溯撤销:递归调用返回后,使用 path.pop() 撤销上一次选择,从而恢复到上一步的状态,准备尝试其他选择。
  2. 剪枝优化技巧
    在 for 循环中,通过判断 len(path) + (n - i + 1) < k 来判断剩余的数字数量是否足够凑齐 k 个数。如果不足,则直接 break,避免无谓的递归调用,从而提高效率。
    由于需要枚举所有的组合,在最坏情况下,组合数量会非常大,但通过剪枝可以在一定程度上减小实际递归调用的次数。

  3. 递归与状态保存:在递归过程中,path 用于保存当前构造的组合状态,使用 path.copy() 保证加入结果集的是当前状态的一个副本,避免后续修改影响已经保存的组合

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值