方法1:
通过dfs,穷举所有的可能,然后判断每一种可能,是否合法。


public static List<String> generateParenthesis(int n) {
List<String> ans = new ArrayList<>();
char[] par = new char[2*n];
getAll(par,0,2*n,ans);
return ans;
}
public static void getAll(char[] par,int pos,int len,List<String> ans){
if(pos==len){
if(vaild(par)){
ans.add(new String(par));
}
return;
}
par[pos]='(';
getAll(par,pos+1,len,ans);
par[pos]=')';
getAll(par,pos+1,len,ans);
}
public static boolean vaild(char[] par){
int count =0;
for(int i=0;i<par.length;i++){
if(count<0) break;
if(par[i]=='(') count++;
if(par[i]==')') count--;
}
if(count==0) return true;
return false;
}
方法2:
我们在dfs的时候,可以改变策略。我们记录左括号个个数和右括号的个数。然后只有当左括号个数<n时,我们添加一个左括号。当右括号个数<左括号时,我们添加右括号。这样我们就只生成了合理的结果。


public static List<String> generateParenthesis(int n) {
List<String> ans = new ArrayList<>();
StringBuilder par = new StringBuilder();
getAll(par,0,0,n,ans);
return ans;
}
public static void getAll(StringBuilder par,int left,int right,int len,List<String> ans){
if(par.length()==2*len){
ans.add(par.toString());
return;
}
if(left<len){
par.append('(');
getAll(par,left+1,right,len,ans);
par.deleteCharAt(par.length()-1);
}
if(right<left){
par.append(')');
getAll(par,left,right+1,len,ans);
par.deleteCharAt(par.length()-1);
}
}
我们重点来看一下这个dfs,这里涉及到回溯:
public static void getAll(StringBuilder par,int left,int right,int len,List<String> ans){
if(par.length()==2*len){
ans.add(par.toString());
return;
}
if(left<len){ ----------------------> a
par.append('(');
getAll(par,left+1,right,len,ans);
par.deleteCharAt(par.length()-1); ------------------->c
}
if(right<left){ ----------------------->b
par.append(')');
getAll(par,left,right+1,len,ans);
par.deleteCharAt(par.length()-1);
}
}
最上面几层:a (
a( a(
a( a( a( ,然后
a( a( a( b) b) b) ,执行到6层深度之后, 碰到第一个return。 ((()))
然后就一直回溯:
a( a( a( c -------> a( a( c[删掉一个左括号] b) a( b) b) 第二个return (()())
然后继续回溯 ,神奇。
来源:oschina
链接:https://my.oschina.net/u/4295775/blog/3227402