0%

leetcode题解22:括号生成

描述

该题来自于力扣第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,那么当前层也可以是);否则结束,所有括号添加完毕。

树生成后,可以使用深度优先遍历所有的路径得到结果,这里可以采用递归的写法,注意一点就是遍历到叶子结点后,需要回溯到初始状态,具体可以看算法说明。

算法

  1. 初始化n,left=right=0,以及路径s=""
  2. 递归函数f(n, left, rihgt, s)
  3. 进入递归主体,如果len(s)==2*n,表明s已经包含了所有括号,添加到结果列表中,并退出函数
  4. 如果left < n,这时添加(,进入函数f(n, left+1, right, s+"("),这里s+"("写在函数形参内,刚好避免回溯时s不受影响,s的变化至于该路径的前面所有层有关。
  5. 如果right < n,这时添加),进入函数f(n, left, right, s+")")

具体算法执行步骤可以这么理解:
首先一直添加(直到无法添加为止,然后添加)直到无法添加为止,即一直遍历树的左节点,然后开始回溯,这时s((())),根据算法会回溯到s="(("即第二层的左节点也是步骤4的结尾,之后进入步骤5。依次下去。

代码

python3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
def generateParenthesis(self, n):
self.n = n
self.result = []
self.generate(0, 0)
return self.result

def generate(self, left, right, s=""):
if len(s) == self.n * 2:
self.result.append(s)
return

if left < self.n:
self.generate(left+1, right, s+"(")

if right < left:
self.generate(left, right+1, s+")")
c++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
vector<string> arr;
public:
vector<string> generateParenthesis(int n) {
generate(0, 0, "", n);
return arr;
}

void generate(int left, int right, string s, int n){
if(s.size() == 2 * n) {
arr.push_back(s);
return;
}
if(left < n){
generate(left+1, right, s+"(", n);
}
if (right < left){
generate(left, right+1, s+")", n);
}
}
};
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
List<String> res = new ArrayList<>();
public List<String> generateParenthesis(int n) {
generate(n, 0, 0, "");
return res;
}

void generate(int n, int left, int right, String s){
if (s.length() == 2*n) {
res.add(s);
return;
};

if (left < n){
generate(n, left+1, right, s+"(");
}

if (right < left){
generate(n, left, right+1, s+")");
}
}
}