描述
该题来自于力扣第22题
数字n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且有效的括号组合。
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1
输出:["()"]
提示:
1 <= n <= 8
分析
要生成有效的括号,第一个字符必然是左括号(
,那么第二个有可能是(
或者)
,以n=3
为例,生成有效括号的过程应该如下:
可以看出是一颗二叉树,二叉树的每条路径对应着一个有效括号组合,所以关键在于如何生成这颗树。思路也很简单,第一层已经确定只能是(
,由于n=3
表示最多可以有3
个(
,所以第二层可能是(
,也可能是)
,那第三层如何确定呢?
假如第二层选择的是(
,由于左括号的个数为2,小于n
,所以第三层也可能是(
或者)
;如果第二层选择的是)
,一样的分析。
第三层如果选择的是(
,这是左括号的个数已经等于n
,所以第四层只能添加)
了。
综上分析可知,假设当前层已有的左括号个数为left
,已有右括号个数为right
,若left<n
,则当前层可以为(
,同时若right<left
,那么当前层也可以是)
;否则结束,所有括号添加完毕。
树生成后,可以使用深度优先遍历所有的路径得到结果,这里可以采用递归的写法,注意一点就是遍历到叶子结点后,需要回溯到初始状态,具体可以看算法说明。
算法
- 初始化
n
,left=right=0
,以及路径s=""
- 递归函数
f(n, left, rihgt, s)
- 进入递归主体,如果
len(s)==2*n
,表明s
已经包含了所有括号,添加到结果列表中,并退出函数 - 如果
left < n
,这时添加(
,进入函数f(n, left+1, right, s+"(")
,这里s+"("
写在函数形参内,刚好避免回溯时s
不受影响,s
的变化至于该路径的前面所有层有关。 - 如果
right < n
,这时添加)
,进入函数f(n, left, right, s+")")
具体算法执行步骤可以这么理解:
首先一直添加(
直到无法添加为止,然后添加)
直到无法添加为止,即一直遍历树的左节点,然后开始回溯,这时s
为((()))
,根据算法会回溯到s="(("
即第二层的左节点也是步骤4的结尾,之后进入步骤5。依次下去。
代码
python3
1 | class Solution: |
c++
1 | class Solution { |
java
1 | class Solution { |