组合与括号生成(回溯)

本篇基于b站灵茶山艾府

77. 组合

给定两个整数 nk,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

复制代码
输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

示例 2:

复制代码
输入:n = 1, k = 1
输出:[[1]]

python 复制代码
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        ans = []
        path = []

        # 1.方法1:每个节点有选/不选分支,在叶子节点处收割结果
        # def dfs(i):
        #     if i > n:
        #         if len(path) == k:
        #             ans.append(path.copy())
        #         return
        #     dfs(i + 1)
        #     path.append(i)
        #     dfs(i + 1)
        #     path.pop()

        # dfs(1)
        # return ans

        # 2.方法2:没有不选的分支,必须选后面的一个元素,且在每个节点处收割结果
        def dfs(i):
            d = k - len(path)  # 代表还需要d个数
            if i < d:
                return  # 剪枝,代表下面继续递归也没法找出d个数存进path数组了
            if len(path) == k:
                ans.append(path.copy())
                return  # 必须return,不然path数组长度会大于k不满足条件

            for j in range(i, 0, -1):  # 倒序
                path.append(j)
                dfs(j - 1)
                path.pop()  # 回溯

        dfs(n)
        return ans

216. 组合总和 III

找出所有相加之和为 nk 个数的组合,且满足下列条件:

  • 只使用数字1到9
  • 每个数字 最多使用一次

返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例 1:

复制代码
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。

示例 2:

复制代码
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。

示例 3:

复制代码
输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

python 复制代码
class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        ans = []
        path = []

        # 方法1:选/不选思路,到叶子节点处收割结果
        # def dfs(i):
        #     if sum(path) > n or len(path) > k:
        #         return  # 剪枝
        #     if i > 9:
        #         if sum(path) == n and len(path) == k:
        #             ans.append(path.copy())
        #         return
        #     dfs(i + 1)
        #     path.append(i)
        #     dfs(i + 1)
        #     path.pop()

        # dfs(1)
        # return ans

        # 方法2:必须选一个后面的数,每个节点处收割结果
        def dfs(i):
            d = k - len(path)
            if i < d:  # 剪枝
                return

            if len(path) == k and sum(path) == n:
                ans.append(path.copy())
                return

            for j in range(i, 0, -1):
                path.append(j)
                dfs(j - 1)
                path.pop()

        dfs(9)
        return ans

22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

复制代码
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

示例 2:

复制代码
输入:n = 1
输出:["()"]

python 复制代码
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        # 每个字符的前缀中左括号的个数必须大于等于右括号,且左括号和右括号的总个数都是n
        # 用选/不选的思路,选的时候就放左括号,不选就放右括号
        # ans = []
        # path = [""] * 2 * n

        # def dfs(i, left):
        #     if i == 2 * n:
        #         ans.append("".join(path))
        #         return
        #     # 如果左括号个数小于n,则可以放左括号
        #     if left < n:
        #         path[i] = "("
        #         dfs(i + 1, left + 1)

        #     # 如果右括号个数小于左括号,则可以放右括号
        #     if i - left < left:
        #         path[i] = ")"
        #         dfs(i + 1, left)

        # dfs(0, 0)
        # return ans

        # 上面不用pop回溯的原因是每次右括号已经把左括号的值覆盖了
        # 若一开始不设置path数组大小,每次都append进去括号,就要pop回溯
        ans = []
        path = []

        def dfs(i, left):
            if i == 2 * n:
                ans.append("".join(path))
                return
            # 如果左括号个数小于n,则可以放左括号
            if left < n:
                path.append("(")
                dfs(i + 1, left + 1)
                path.pop()

            # 如果右括号个数小于左括号,则可以放右括号
            if i - left < left:
                path.append(")")
                dfs(i + 1, left)
                path.pop()

        dfs(0, 0)
        return ans

相关推荐
PPPPPaPeR.8 小时前
光学算法实战:深度解析镜片厚度对前后表面折射/反射的影响(纯Python实现)
开发语言·python·数码相机·算法
JaydenAI8 小时前
[拆解LangChain执行引擎] ManagedValue——一种特殊的只读虚拟通道
python·langchain
看我干嘛!8 小时前
python第五次作业
算法
骇城迷影8 小时前
Makemore 核心面试题大汇总
人工智能·pytorch·python·深度学习·线性回归
历程里程碑8 小时前
Linux 库
java·linux·运维·服务器·数据结构·c++·算法
长安牧笛8 小时前
反传统学习APP,摒弃固定课程顺序,根据用户做题正确性,学习速度,动态调整课程难度,比如某知识点学不会,自动推荐基础讲解和练习题,学习后再进阶,不搞一刀切。
python·编程语言
Sheep Shaun8 小时前
如何让一个进程诞生、工作、终止并等待回收?——探索Linux进程控制与Shell的诞生
linux·服务器·数据结构·c++·算法·shell·进程控制
Pluchon8 小时前
硅基计划4.0 简单模拟实现AVL树&红黑树
java·数据结构·算法
生锈的键盘9 小时前
推荐算法实践:交叉特征的理解
算法