方法一:暴力
暴力生成所有可能的括号组成,对于每个组成判断是否合理。
class Solution {
public List<String> generateParenthesis(int n) {
List<String> res=new ArrayList<String>();
dfs(res,0,new char[2*n]);
return res;
}
void dfs(List<String> res,int pos,char[] cur){
if(pos==cur.length){
if(valid(cur)==true){
res.add(new String(cur));
}
return;
}
cur[pos]='(';
dfs(res,pos+1,cur);
cur[pos]=')';
dfs(res,pos+1,cur);
}
boolean valid(char[] cur){
int cnt=0;
for(int i=0;i<cur.length;i++){
if(cur[i]=='(') cnt++;
else cnt--;
if(cnt<0) return false;
}
return cnt==0;
}
}
方法二:回溯
对暴力方法做优化:不需要每次都生成完整的括号组,应该“及时止损”,当前已经出错时,就应该中止当前正在生成的字符串。
怎样判断当前字符串合理,可以继续:
- 左括号个数小于n,可以继续增加左括号;
- 右括号个数小于左括号个数,可以继续增加右括号。
当前情况已经错误时,需要回溯,此时要将在同一位置之前添加的括号删除掉。因此选用stringbuffer,便于字符串的添加和删除。
class Solution {
public List<String> generateParenthesis(int n) {
List<String> res=new ArrayList<String>();
dfs(res,new StringBuffer(),0,0,n);
return res;
}
private void dfs(List<String> res,StringBuffer cur,int left,int right,int n){
if(cur.length()==n*2){
res.add(cur.toString());
return;
}
if(left<n){
cur.append('(');
dfs(res,cur,left+1,right,n);
cur.deleteCharAt(cur.length() - 1);
}
if(right<left){
cur.append(')');
dfs(res,cur,left,right+1,n);
cur.deleteCharAt(cur.length() - 1);
}
}
}