题目描述:
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
输入输出示例:
输入:
n=3
输出:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
对于该题有两种解题方法:回溯法 和 暴力求解法
解法一:回溯法
回溯法在上一篇博客中有提到,这里只展示使用回溯法解决该问题的思路;
解题思路:
- 使用left,right来记录结果中‘(’ 和‘)’的个数;
- 最开始设左括号的个数为N个,不但要用来给左括号计数,还要作为回溯结束(left==0)的一部分条件;
- 因为要保证结果的有效性,所以每添加一个‘(’就要在后边出现一个‘)’与之对应;因此,每当left的计数-1时,right的计数就要+1;
- 当添加一个 ‘)’ 时,只需要将右括号的计数-1即可;
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
BackTrack(res,"",n,0);//第一个填入的一定是‘(’
return res;
}
void BackTrack(vector<string>& res,string str,int left,int right)
{
if(left==0 && right==0)
{
res.push_back(str);
return ;
}
if(left > 0)
BackTrack(res,str+'(',left-1,right+1);//当给结果中加入一个‘(’,就要保证在后边会有一个‘)’与其匹配
if(right > 0)
BackTrack(res,str+')',left,right-1);
}
};
解法二:暴力求解法
解题思路:
- 先将比较特殊的情况单独处理(n为1和n为0),直接返回结果;
- 针对其他情况使用暴力求解的方法:
- 暴力求解即:列出所有的可能情况,再将不合格的结果剔除。
- 罗列所有的可能情况使用next_permutation()这个函数;
- 使用next_permutation()函数处理的对象默认是升序的;
注意:因为每个结果的第一个元素一定是‘(’,所以在重新排列时,第一个元素不参与;
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
if(n==0)
return res;
if(n==1)
{
res.push_back("()");
return res;
}
string s = "";
for(int i = 0 ;i < n;++i)
s+="()";
sort(s.begin(),s.end());
do{
if(IsLegal(s))
res.push_back(s);
}while(next_permutation(s.begin()+1,s.end()));
return res;
}
//判断结果的有效性
bool IsLegal(string& s)
{
int count = 0;
for(int i = 0;i < s.size();++i)
{
if(s[i]=='(')
count++;
else
count--;
if(count<0)
return false;
}
return true;
}
};