题目描述:
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
算法1:暴力法:
列出所有可能的序列,然后判断其中有哪些序列是合理的。
虽然AC了,但是当 n = 10 时,就会超出时间限制,给的测试数据比较小。
复杂度分析参考:LeetCode官方题解方法一
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string>ans;
if(n==0)
return ans;
vector<string>res;
for(int i=0; i<2*n; i++)
res.push_back("()");
generate(n, res, ans, "", 0);
return ans;
}
void generate(int n, vector<string>& res, vector<string>& ans, string out, int level)
{
if(out.size() == 2*n)
{
if(check(out))
ans.push_back(out);
return;
}
string temp = res[level];
for(int i=0; i<temp.size(); i++)
{
generate(n, res, ans, out+temp[i], level+1);
}
}
bool check(string& out)
{
stack<char>st;
for(auto& s: out)
{
if(st.empty())
st.push(s);
else
{
if(s == ')' && st.top()=='(')
st.pop();
else
st.push(s);
}
}
return st.empty() ? true: false;
}
};
算法二:回溯法
不需要生成所有可能的字符串。我们知道序列仍然保持有效时才添加
'('
or')'
,如果我们还剩一个位置,我们可以开始放一个左括号。 如果它不超过左括号的数量,我们可以放一个右括号。
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string>ans;
if(n==0)
return ans;
dfs(0, 0, ans, "",n);
return ans;
}
void dfs(int left, int right, vector<string>& ans, string out,int n)
{
if(left < right)
return ;
else if(left == n && right == n)
{
ans.push_back(out);
}
else
{
if(left > right)
dfs(left, right+1, ans, out + ')', n);
if(left<n)
dfs(left+1, right, ans, out + '(', n);
}
}
};