(day28)leecode——有效括号

描述

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

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

示例 2:

输入:n = 1
输出:["()"]

提示:

  • 1 <= n <= 8

leecode题解灵茶山艾府 

枚举填左括号还是右括号

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        ans = []  # 初始化一个空列表,用于存储最终生成的所有有效括号组合
        m = n * 2  # 计算所有括号的总长度,因为一个有效的括号组合由n个左括号和n个右括号组成,所以长度为n*2
        path = [''] * m  # 初始化一个长度为m的空字符列表,用于构建括号组合

        # 定义一个深度优先搜索(DFS)函数,用于生成括号组合
        # i 表示当前填入括号的位置
        # open 表示已经放入的左括号数量
        # i-open 表示已经放入的右括号数量
        def dfs(i: int, open: int) -> None:
            if i == m:  # 如果当前填入的位置已经达到总长度m,说明已经生成了一个完整的括号组合
                ans.append(''.join(path))  # 将当前生成的括号组合加入结果列表
                return
            if open < n:  # 如果左括号数量还未达到n个,可以继续放入左括号
                path[i] = '('  # 在当前位置放入一个左括号
                dfs(i + 1, open + 1)  # 递归调用DFS,位置后移一位,左括号数量加一
            if i - open < open:  # 如果右括号数量少于左括号数量,可以放入右括号
                path[i] = ')'  # 在当前位置放入一个右括号
                dfs(i + 1, open)  # 递归调用DFS,位置后移一位,左括号数量不变

        dfs(0, 0)  # 从位置0开始,初始左括号数量为0
        return ans  # 返回生成的所有有效括号组合
整体分析
  • 初始化数据结构

    • 创建一个空列表 ans,用于存储所有有效的括号组合。
    • 计算括号组合的总长度 m,即 n * 2
    • 创建一个长度为 m 的空字符列表 path,用于构建括号组合。
  • 深度优先搜索函数定义

    • 定义一个递归函数 dfs(i, open)
      • i 表示当前正在填入括号的位置。
      • open 表示当前已经放入的左括号数量。
    • i 等于 m 时,即已经填入了 m 个位置,将当前 path 中的括号组合转换为字符串并加入到 ans 中。
  • 递归生成括号组合

    • 如果 open 小于 n,可以在当前位置 i 放入一个左括号 '(',递归调用 dfs(i + 1, open + 1)
    • 如果 i - open 小于 open,即右括号数量少于左括号数量,可以在当前位置 i 放入一个右括号 ')',递归调用 dfs(i + 1, open)
  • 启动递归

    • 调用 dfs(0, 0),从位置0开始,初始左括号数量为0,开始生成所有有效的括号组合。
  • 返回结果

    • 返回存储在 ans 列表中的所有有效括号组合。

 

复杂度分析

 
时间复杂度:分析回溯问题的时间复杂度,有一个通用公式:路径长度×搜索树的叶子数。对于本题,它等于 O(n⋅C(2n,n))。但由于左右括号的约束,实际上没有这么多叶子,根据 Catalan 数,只有  个叶子节点,所以实际的时间复杂度为 O(C(2n,n))。此外,根据阶乘的 Stirling 公式,时间复杂度也可以表示为 
空间复杂度:O(n)。返回值的空间不计入。

枚举下一个左括号的位置

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        ans = []  # 用于存储所有合法的括号组合
        path = []  # 用于记录当前生成的括号组合的路径
        
        def dfs(i: int, balance: int) -> None:
            # i:当前正在处理的括号的位置
            # balance:当前路径中的左括号数量减去右括号数量
            
            if len(path) == n:
                # 如果路径长度等于 n,则说明当前路径已经形成了一对合法括号
                s = [')'] * (n * 2)  # 初始化括号数组,全用右括号
                for j in path:
                    s[j] = "("  # 将路径中的位置设为左括号
                ans.append(''.join(s))  # 形成完整的括号组合并添加到答案中
                return  # 结束当前递归
            
            # 遍历可能的右括号位置
            for close in range(balance + 1):
                path.append(i + close)  # 将当前的括号位置添加到路径中
                dfs(i + close + 1, balance - close + 1)  # 递归调用,更新位置和余额
                path.pop()  # 撤销当前位置,回溯到上一个状态
        
        dfs(0, 0)  # 初始调用
        return ans  # 返回所有合法括号组合
 整体分析
  • 初始化:创建一个列表 ans 来存储所有合法的括号组合,同时创建一个空列表 path 用于记录当前生成的括号路径。

  • 定义递归函数

    • 参数:函数 dfs 接受两个参数:i 表示当前处理的位置,balance 表示当前路径中左括号和右括号的差值(即平衡度)。
    • 检查完成状态:如果当前路径的长度等于 n,说明当前路径代表一个完整的合法括号组合。接着根据 path 中记录的位置构建这个组合的字符串,并将其添加到结果列表 ans 中。
  • 生成组合

    • 遍历可能的右括号位置,根据当前的平衡度确定可能的位置。
    • 将当前位置添加到 path 中,并递归调用 dfs 函数来继续生成下一个位置的括号组合。
    • 递归返回后,从 path 中移除当前位置,以便回溯到之前的状态,尝试其他可能的组合。
  • 开始递归:从初始状态调用 dfs 函数,开始生成括号组合。

  • 返回结果:所有合法的括号组合生成完成后,返回存储这些组合的列表 ans

Leecode题解小笨蛋

 

 一个满二叉树,我们只需要DFS所有节点即可。先把所有组合给生成出来,即DFS所有节点。把不符合的给过滤掉结束DFS。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值