Generate Parentheses - LeetCode
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given $n = 3$, a solution set is:
1
2
3
4
5
6
7 [
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
错误理解
因为题目中给了 $n = 3$ 的例子,因此,思维定式地考虑:对于所有 $n=k$ 的括号串 s_i,分别构造 ()s_i、s_i() 和 (s_i),形成 $n=k+1$ 的所有可能括号串。
显然,如果验证一次 $n=4$ 就容易想到这种思路是错误的,因为没有考虑到这三种情况未能包括的其他情况,如:(())(()),这可以视为两个 $n=2$ 的括号串的拼接。
Brute Force
Brute Force 方法是将 $2^2n$ 种由 ( 和 ) 组成的括号串依次检验其是否符合规则。检验时根据 # of ( - # of ) >= 0 来判断。
不再赘述。
解决两个子问题
上述错误思路实际上是来源于一个(正确的)思路:即解决一个基数较小的不相交子集的「总和」。思考如何用 $n<k$ 的已经计算的符号串集合来求解 $n=k$ 时的问题。
我最终提交的 AC 答案思路是:先将 $n=k-1$ 的所有符号串构造成 (...) 并加入 ans。另外考虑 i = 1..k-1 时所形成的每一个符号串 left,与 j = n - i 所形成的每个符号串 right,将两者拼接起来形成一种可能的符号串,并加入 ans。通过双层循环语句实现。
本题的 Solution 部分给出了这种方法的一个更简洁的描述。
- 定义一个有效括号串
S的 closure number 为:使得S[0],S[1], …,S[2*index+1]有效的index >= 0的最小值。每个括号串有唯一的 closure number。 - 对每个括号串,考虑其 closure number
c:S[0]和S[2*c + 1]一定分别为(和),而且其间的2*c个括号形成的串一定也有效。加上剩余部分(也是有效的括号串),就形成了完整的括号串。
1 | class Solution { |
时间和空间复杂度均为 $O \left ( \frac{4^n}{\sqrt{n}} \right )$。
回溯
回溯方法通过 DFS 的方式不断构造字符串,当括号串合法时(以长度达到 2n 或右括号数目达到 n 为停止条件)添加到 ans 中。回溯方法需要维持已经放置的左右括号数目用于构造下一个括号串。
- 如果
(未超过n,可以放置(; - 如果左括号数大于右括号数,可以放置
)。
上述两个候选字符串可以同时成立,或只有一个成立。
1 | class Solution { |
时间复杂度与上述方法相同。