LeetCode:22. 括号生成

本文详细解析了LeetCode括号生成问题的两种解法:暴力破解与回溯法。介绍了如何通过递归生成所有可能的括号组合,并在过程中检查其有效性,避免无效组合的生成。

LeetCode:括号生成

问题描述

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且有效的括号组合。
示例:
输入:n = 3
输出:[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

解题

方法一:暴力破解

(1)生成所有序列
利用递归生成所有序列,下图有助于理解生成过程:ter)
通过递归生成序列的过程就是对树的遍历过程。
在这里插入图片描述
注意到这颗树的根节点是一个左括号,这样做直接省去了第一个括号是右括号这个错误的情况

(2)检查是否有效

对一个生成的序列从左到右遍历的时候左括号的个数必须始终大于等于又括号的个数这个序列才符合要求。比如"())("就不符合要求。
另外对一个生成的序列从左到右遍历的时候只要左括号的数量大于n那么这个序列也不符合要求。

(3)如何进行递归
实际上(1)和(2)都是为了用递归的思路解决这个问题做的铺垫,这道题可以用递归的原因是:生成长度为2n的字符数组等价于生成第一个字符加上生成剩下的2n-1个字符。参考3道题彻底搞定:套路解决递归问题中的方法我们对这道题进行分析:
递归三部曲:

  1. 终止条件:生成了长度为2n的括号组且符合生成要求
  2. 本级递归需要做什么:往括号组里面添加或者删除左括号或者右括号,用来生成新的括号组
  3. 返回值是什么:所生成的符合要求的所有可能的括号组

具体代码如下:

class Solution:
    def generate_parenthesis(self, n):
        def generate(A):
        	# 终止条件(START)
            if len(A) == 2*n:
                if valid(A):
                    ans.append("".join(A))
           # 终止条件(END)
           
           # 本级递归需要做的事(START)
            else:
                A.append('(')
                generate(A)
                A.pop()
                A.append(')')
                generate(A)
                A.pop()
			# 本级递归需要做的事(END)
			
        def valid(A):
            bal = 0
            for c in A:
                if c == '(':
                    bal += 1
                else:
                    bal -= 1
                if bal > n or bal < 0:  
                    return False
            return bal == 0

        ans = []
        generate([])
        
        # 返回值
        return ans


if __name__ == '__main__':
    solution = Solution()
    result = solution.generate_parenthesis(3)
    print(result)

方法二:回溯法

方法二其实是对方法一的改进,因为方法一中直到生成长度为2n的括号组之后才去判断这个括号组的有效性,但实际上在括号组生成的过程中当右括号的数量大于左括号的数量时这个括号组就已经无效了,所以可以在中间进行判断从而改进算法。

LeetCode官方的程序:

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        ans = []
        def backtrack(S, left, right):
            if len(S) == 2 * n:
                ans.append(''.join(S))
                return
            if left < n:
                S.append('(')
                backtrack(S, left+1, right)
                S.pop()
            if right < left:
                S.append(')')
                backtrack(S, left, right+1)
                S.pop()

        backtrack([], 0, 0)
        return ans

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

comli_cn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值