1. Problem
给定n对括号,生成所有可能的括号组合
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. For example, given n = 3, a solution set is: "((()))", "(()())", "(())()", "()(())", "()()()"
2. Solution
采用树的方式来选择生成所有的组合结果树,每种组合是树的一个遍历分支。
有两种方法,基本一样的。
第一种,定义三个变量:
- lLeft:表示还没有用的左括号数;
- rLeft:表示还没有用的右括号数;
- now:表示当前已用的字符串;
其中lLeft<=rLeft始终成立。则有如下判断:
- lLeft == 0:左括号用完,加上剩下的右括号,构建一个完整的串;
- lLeft != 0:
- 接下来可以加一个左括号(总是可以)
- 如果lLeft < rLeft,则接下来也可以加一个右括号
代码如下:
1 public class Solution { 2 List<String> res; 3 public void dfs( String now, int lLeft, int rLeft ){ 4 if( lLeft == 0 ){ 5 char[] rLeftString = new char[rLeft]; 6 for( int i=0; i<rLeft; i++ ) 7 rLeftString[i] = ')'; 8 res.add( now + String.valueOf(rLeftString) ); 9 } 10 else{ 11 dfs( now + "(", lLeft-1, rLeft ); 12 if( lLeft < rLeft ) 13 dfs( now + ")", lLeft, rLeft-1 ); 14 } 15 } 16 17 public List<String> generateParenthesis( int n ){ 18 res = new ArrayList<String>(); 19 dfs( "", n, n ); 20 return res; 21 } 22 }
第二种,定义三个变量:
- i:表示已配成对的括号数,初始为0;
- j:表示当前未配对的左括号,初始为1(如果n>0);
- next:当前节点的下一个节点值
则有如下判断(以n=3为例,用0代表左括号,1代表右括号):
- i==3:终止
- i!=3:
- i+j == 3, next=1, i++, j--; //意味着所有的左括号都已经出现了,但是仍未完成配对
- i+j != 3 //左括号还没有出现完
- j>0 //当前还有左括号未配对
- next=0, j++;
- next=1, i++, j--;
- j==0, next=0, j++ //当前的左括号都已配对
- j>0 //当前还有左括号未配对
下图是n=3时的判断实例,其中最左的一个分支是((())),第二个是(()()):
代码如下:
public class Solution { List<String> res; public void expand( String now, int i, int j, int n ){ //finish matching if( i == n ){ res.add( now ); return; } //all left parentheses are used if( i + j == n ) expand( now + ")", i+1, j-1, n ); //there're still unused left parentheses else{ //there're still unmatched left parentheses if( j > 0 ){ expand( now + "(", i, j+1, n ); expand( now + ")", i+1, j-1, n ); } //all used left parentheses are matched at present else if( j == 0 ) expand( now + "(", i, j+1, n ); } } public List<String> generateParenthesis( int n ){ res = new ArrayList<String>(); expand( "(", 0, 1, n ); return res; } }