Generate Parentheses
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:
“((()))”, “(()())”, “(())()”, “()(())”, “()()()”
Solution1
- 可以这么思考这道题,当n=3时:
- 如果目前左括号全用完了,则必须得先加入一个左括号;
- 如果已用过的左括号已经达到n了,则后面都加入右括号直到匹配完全,比如”()((“;
- 如果目前还有未匹配的左括号且左括号数还不到极限,则既可以加入左括号也可以加入右括号,例如”(()”
- 代码表示如下:
import java.util.*;
public class Solution {
public List<String> generateParenthesis(int n) {
ArrayList<String> result = new ArrayList<String>();
help(n,0,0,result,new StringBuffer());
return result;
}
public void help(int n, int total, int count, List<String> result, StringBuffer s){
if(total==n){//所有左括号全用完,则后面只需要加入右括号
while(count-->0) s.append(')');
result.add(s.toString());
return;
}
if(count==0){//目前没有左括号了
s.append('(');
help(n, total+1, count+1, result, s);//首先在这里调用函数时不能用total++和count++,这样实际上只有在调用函数后才会加1,另外++total和++count也不行,这样会改变total和count的值,而这会影响到下面的程序
}else{//左括号还剩余并且左括号数还不到极限
StringBuffer sb = new StringBuffer(s);
sb.append('(');
help(n, total+1, count+1, result, sb);
s.append(')');
help(n, total, count-1, result, s);
}
}
}
Solution2
- 效率更高,代码更直观的解决方法是分别记录当前用了多少个左括号和右括号,如果:
- 左括号个数小于n,则继续添加左括号;
- 左括号个数多于右括号个数,则表明此时可以添加右括号。
- 代码表示如下:
import java.util.*;
public class Solution {
public List<String> generateParenthesis(int n) {
ArrayList<String> result = new ArrayList<String>();
help2(n,0,0,result,new StringBuffer());
return result;
}
public void help2(int n, int left, int right, List<String> result, StringBuffer s){
if(left==n&&right==n){
result.add(s.toString());
return;
}
if(left<n){
StringBuffer sb = new StringBuffer(s);//这里必须得创建一个新的样本出来
help2(n,left+1,right,result,sb.append('('));
}
if(left>right) help2(n,left,right+1,result,s.append(')'));
}
}
Solution3
- 如果不用StringBuffer,代码还可以看起来更整洁一些。因为StringBuffer用的时候还得先创建一个新的样本出来。
import java.util.*;
public class Solution {
public List<String> generateParenthesis(int n) {
ArrayList<String> result = new ArrayList<String>();
help3(n,0,0,result,"");
return result;
}
public void help3(int n, int left, int right, List<String> result, String s){
if(left==n&&right==n){
result.add(s);
return;
}
if(left<n) help3(n,left+1,right,result,s+'(');
if(left>right) help3(n,left,right+1,result,s+')');
}
}
Solution4
- 这题还有一种更高深的方法:动态规划。这种方法非常巧妙,一般不易想到,并且理解起来没有上述解法那么直接。
f(0): “”
f(1): “(“f(0)”)”
f(2): “(“f(0)”)”f(1), “(“f(1)”)”
f(3): “(“f(0)”)”f(2), “(“f(1)”)”f(1), “(“f(2)”)”
So f(n) = “(“f(0)”)”f(n-1) , “(“f(1)”)”f(n-2) “(“f(2)”)”f(n-3) … “(“f(i)”)”f(n-1-i) … “(f(n-1)”)”
- 代码如下:
import java.util.*;
public class Solution {
public List<String> generateParenthesis(int n) {
ArrayList<List<String>> temp = new ArrayList<List<String>>();//用来保存所有中间结果
ArrayList<String> item = new ArrayList<String>();
item.add("");
temp.add(item);
for(int i=1;i<=n;i++){
item = new ArrayList<String>();//本次要生成为n=i时的所有组合
for(int j=0;j<i;j++){//这三个for循环构成了递推式
for(String first:temp.get(j)){
for(String second:temp.get(i-j-1)){
item.add("("+first+")"+second);
}
}
}
temp.add(item);
}
return temp.get(temp.size()-1);
}
}
- 这种方法引用自动态规划的解法