括号生成

原题点这里

方法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;
    }
View Code

方法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);
        }
    }
View Code

我们重点来看一下这个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  (()())

      然后继续回溯  ,神奇。

原文地址:https://www.cnblogs.com/superxuezhazha/p/12669519.html