组合与括号生成(回溯)

本篇基于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

相关推荐
大千AI助手2 小时前
DTW模版匹配:弹性对齐的时间序列相似度度量算法
人工智能·算法·机器学习·数据挖掘·模版匹配·dtw模版匹配
烛阴3 小时前
简单入门Python装饰器
前端·python
YuTaoShao4 小时前
【LeetCode 热题 100】48. 旋转图像——转置+水平翻转
java·算法·leetcode·职场和发展
好开心啊没烦恼4 小时前
Python 数据分析:numpy,说人话,说说数组维度。听故事学知识点怎么这么容易?
开发语言·人工智能·python·数据挖掘·数据分析·numpy
生态遥感监测笔记4 小时前
GEE利用已有土地利用数据选取样本点并进行分类
人工智能·算法·机器学习·分类·数据挖掘
面朝大海,春不暖,花不开4 小时前
使用 Python 实现 ETL 流程:从文本文件提取到数据处理的全面指南
python·etl·原型模式
Tony沈哲4 小时前
macOS 上为 Compose Desktop 构建跨架构图像处理 dylib:OpenCV + libraw + libheif 实践指南
opencv·算法
刘海东刘海东5 小时前
结构型智能科技的关键可行性——信息型智能向结构型智能的转变(修改提纲)
人工智能·算法·机器学习
2301_805054565 小时前
Python训练营打卡Day59(2025.7.3)
开发语言·python