地址:https://leetcode.com/problems/generate-parentheses/
题目:
Given n
pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given
n
n
n = 3, a solution set is:
Example:
理解:
想到了检验是否是有效序列的那道题。
另外,数据结构里经常出的几个数字出入栈的所有可能情况也是一样的。对于有
n
n
n个数的集合,出入栈情况可以用卡特兰数(Catalan number)计算:
1
n
+
1
C
2
n
n
\frac{1}{n+1}C_{2n}^{n}
n+11C2nn
这道题是要生成所有的有效序列。
一个重要的性质:在当前位置,如果右括号的数目大于左括号的数目,则该序列一定是无效的。
由于是从左到右生成,因此在每一个位置保证当前位置有效,然后继续插入即可。实现有两种,大同小异,一种传递的是剩余的可用括号数,一种是序列里已有的括号数。
实现1:
这种实现left和right是剩余可添加的括号数。
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
generate(n, n, "", res);
return res;
}
void generate(int left, int right, string curr, vector<string>& res) {
if (left >= 0 && right >= 0) {
if (left > right)
return;
if (left == 0 && right == 0)
res.push_back(curr);
else {
generate(left - 1, right, curr + "(", res);
generate(left, right - 1, curr + ")", res);
}
}
}
};
实现2(Backtracking)
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
generate(0, 0, n, "", res);
return res;
}
void generate(int left, int right, const int maxLen, string curr, vector<string>& res) {
if (curr.size() == 2 * maxLen)
res.push_back(curr);
else {
if (left < maxLen)
generate(left + 1, right, maxLen, curr + "(", res);
if (right < left)
generate(left, right + 1, maxLen, curr + ")", res);
}
}
};
复杂度分析:
当可以生成有效的序列时,才会产生函数调用。
卡特兰数的上限有人推导出来是
O
(
4
n
n
)
O\left(\frac{4^n}{\sqrt{n}}\right)
O(n4n)。
- 时间复杂度:
O
(
4
n
n
)
O\left(\frac{4^n}{\sqrt{n}}\right)
O(n4n)。每个有效的序列在backtracking过程中有
n
步。 - 空间复杂度: O ( 4 n n ) O\left(\frac{4^n}{\sqrt{n}}\right) O(n4n),另外有 O ( n ) O(n) O(n)的空间存储序列。