给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
解题思路
这个问题非常简单,我们首先可以想到的解法就是暴力破解,将()()()
所有的排列组合列出来,然后判断那些是有效的括号组合。可以参看Leetcode 20:有效的括号(最详细解决方案!!!)
res = list()
par_list = ['(',')']*n
for par in set(itertools.permutations(par_list)):
par = list(par)
if isValid(par):
res.append(par)
但是显然这种做法不合适,我们有没有更加好的方案呢?我们尝试一下递归该怎么做。我们首先想到的做法就是定义函数 f ( i ) f(i) f(i)返回输入数为n=i
的返回结果,那么现在我们要做的就是找到 f ( i ) f(i) f(i)和 f ( i − 1 ) f(i-1) f(i−1)之间的关系。我们举个例子
n = 3
f(i-1): ["()()", "(())"]
f(1): ["()"]
我们现在要做的就是将f(1)
插入到f(i-1)
的所有元素中去。例如对于第一个元素结果就是
"()()()" "(())()" "()(())"
所以正如你所见,我们应该设计一个set
去存放我们的结果。最后我们按照这种思路去写代码。
class Solution:
def generateParenthesis(self, n):
"""
:type n: int
:rtype: List[str]
"""
if n == 0:
return list()
if n == 1:
return ["()"]
res = set()
tmp = self.generateParenthesis(n-1)
for s in tmp:
for i in range(len(s)):
tmp = s[:i] + "()" + s[i:]
res.add(tmp)
return list(res)
不错的思路。我们还有另外一种思路,就是通过回溯法。
我们可以考虑(
和)
括号的情况。如果我们发现(
的数量小于n
的话,我们就填入(
;如果我们发现)
的数量小于(
的话,我们就填入)
。举个例子n=2
(
我们发现(
的数量小于n
,我们继续填入(
( (
我们发现(
等于n
了,我们就不再填入(
了,然后我们考虑)
的数量小于(
,所以我们填入(
。
( ( ) )
到这里你就会发现一个问题,就是我们忽略了()()
。实际上我们只结束了((
的操作,我们对(
还没有做操作。
我们发现此时)
的数量小于(
了,所以我们要将)
填入。
( )
我们发现(
的数量小于n
,我们继续填入(
,最后基于同样的原理我们填入)
。
( ) ( )
注意,我最后再次强调我们的栈里面是存有((
和(
的(系统栈)。最后的代码
class Solution:
def generateParenthesis(self, n):
"""
:type n: int
:rtype: List[str]
"""
res = list()
self.helper(n ,res, 0, 0, '')
return res
def helper(self, n, res, l, r, par):
if len(par) == 2*n:
res.append(par)
return
if l < n:
self.helper(n, res, l + 1, r, par + '(')
if r < l:
self.helper(n, res, l, r + 1, par + ')')
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!