数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
-
示例 1:
- 输入:n = 3
- 输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”] 示例 2:
- 输入:n = 1
- 输出:[“()”] 提示:
- 1 <= n <= 8
解析
任何一个括号序列都一定是由 ‘(’ 开头,并且第一个 ‘(’ 一定有一个唯一与之对应的 ‘)’。这样一来,每一个括号序列可以用(a)b来表示,其中a与 bbb 分别是一个合法的括号序列(可以为空)。
那么,要生成所有长度为2n的括号序列,我们定义一个函数generate(n)来返回所有可能的括号序列。
-
在函数generate(n)的过程中:
- 我们需要枚举与第一个 ‘(’ 对应的‘)’ 的位置2i+1;
- 递归调用generate(i) 即可计算a的所有可能性;
- 递归调用generate(n−i−1)即可计算b的所有可能性;
- 遍历a与b的所有可能性并拼接,即可得到所有长度为2n的括号序列。
为了节省计算时间,我们在每次generate(i)函数返回之前,把返回值存储起来,下次再调用generate(i)时可以直接返回,不需要再递归计算。
代码
class Solution {
shared_ptr<vector<string>> cache[100] = {nullptr};
public:
shared_ptr<vector<string>> generate(int n) {
if (cache[n] != nullptr)
return cache[n];
if (n == 0) {
cache[0] = shared_ptr<vector<string>>(new vector<string>{""});
} else {
auto result = shared_ptr<vector<string>>(new vector<string>);
for (int i = 0; i != n; ++i) {
auto lefts = generate(i);
auto rights = generate(n - i - 1);
for (const string& left : *lefts)
for (const string& right : *rights)
result -> push_back("(" + left + ")" + right);
}
cache[n] = result;
}
return cache[n];
}
vector<string> generateParenthesis(int n) {
return *generate(n);
}
};