给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
自己想到的解法是,在回溯过程中用一个栈来判断(注意恢复栈的状态),通过,但是效率低下。
vector<string> generateParenthesis(int n) {
string kuohao = "()";
vector<string> res;
string now = "";
stack<char> s;
track(res, now, n * 2, 0, kuohao,s);
return res;
}
void track(vector<string>& res, string now, int n, int visit, string kuohao,stack<char>&s) {
if (visit == n && s.empty()) {
res.push_back(now);
return;
}
for (int i = 0; i < kuohao.size(); i++) {
int flag = 0;
if (s.top() == '(' && kuohao[i] == ')') {
flag = 1;
s.pop();
}
else s.push(kuohao[i]);
track(res, now + kuohao[i], n, visit + 1, kuohao,s);
if (flag == 1) s.push('(');
else s.pop();
}
}
比较巧妙的解法是,要想到左边的括号必须大于右边的括号,否则就会出现)(的情况,是不合法的,同时要保证左右括号都必须<=n。
vector<string> generateParenthesis(int n) {
vector<string> res;
string now;
track(0, 0, res, now, n);
return res;
}
void track(int left, int right, vector<string>& res, string now, int n) {
if (left+right == n*2) {
res.push_back(now);
return;
}
if(left<n) track(left + 1, right, res, now + "(", n);
if (left > right && right<n) {
track(left, right+1, res, now + ")", n);
}
else return;
}