1. 题目来源
链接:22. 括号生成
2. 题目解析
卡特兰数
若为一个合法的括号序列,则有:
- 任意前缀中左括号数量大于对应右括号数量
- 左右括号数量相等
- 若该题不让输出所以方案,而是仅仅输出方案数量的话,方案数量就是卡特兰数: C ( n , 2 n ) n + 1 \frac {C(n, 2n)} { n + 1} n+1C(n,2n)
以上两个结论在括号序列合法判断问题中非常实用,至于合法方案,就是卡特兰数,证明和 满足条件的 01 序列 一模一样。
基于上面的两条结论,可以 dfs
暴力搜索所有的合法方案。一共有 2n
位,每次考虑当前位要填哪种括号。
- 只要左括号数量
l_cnt < n
就能填左括号。 - 只要右括号数量
r_cnt < n && r_cnt < l_cnt
就能填右括号。 dfs
每次考虑两种情况,递归即可。当l_cnt == r_cnt
时则找到合法方案,添加进答案数组中。
- 时间复杂度:
O
(
C
(
n
,
2
n
)
)
O(C(n, 2n))
O(C(n,2n))。所有方案数就是卡特兰数,还要将答案复制到
vector
中,会产生2n
的时间复杂度。故分母可以消去了。 - 空间复杂度: O ( n ) O(n) O(n)。递归的深度。
代码:
class Solution {
public:
vector<string> res;
vector<string> generateParenthesis(int n) {
dfs(n, 0, 0, "");
return res;
}
void dfs(int n, int l, int r, string path) {
if (l == n && r == n) res.push_back(path);
else {
if (l < n) dfs(n, l + 1, r, path + '(');
if (r < n && r < l) dfs(n, l, r + 1, path + ')');
}
}
};