Leetcode 22 Generate Parentheses

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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值