括號生成

方法一:暴力破解

生成所有可能的字符串組合,然後檢查有效的字符串。一共可以生成的字符串個數爲:2^{2n}

爲了生成所有序列,我們使用遞歸。長度爲 n 的序列就是 '(' 加上所有長度爲 n-1 的序列,以及 ')' 加上所有長度爲 n-1 的序列。

爲了檢查序列是否爲有效的,我們會跟蹤平衡,也就是左括號的數量減去右括號的數量的淨值。如果這個值始終小於零或者不以零結束,該序列就是無效的,否則它是有效的。

package leetcode.problem22;


import java.util.ArrayList;
import java.util.List;

class Solution2 {
    
    public static List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<>();
        getAll(new char[2 * n], 0, result);
        return result;
    }

    private static void getAll(char[] chars, int i, List<String> result) {
        if (i == chars.length){
            if (valid(chars)){
                result.add(new String(chars));
            }
            return;
        }else {
            chars[i] = '(';
            getAll(chars, i + 1, result);
            chars[i] = ')';
            getAll(chars, i + 1, result);
        }
    }

    private static boolean valid(char[] chars) {
        int t = 0;
        for (char c : chars){
            if (c == '('){
                t++;
            }else if (c == ')'){
                t--;
            }
            if (t < 0){
                return false;
            }
        }
        return t == 0;
    }

}

複雜度分析:

時間複雜度:O(2^{2n}n),對於每一個子序列驗證其合法性的時間複雜度爲O(n)

空間複雜度:O(2^{2n}n)

方法二:回溯法

先寫n個左括號,然後就寫右括號,每當完成一組之後,就吧字符串存起來。然後再倒退步驟到寫第n-1個左括號,然後寫右括號,在寫左括號,再全寫右括號。依次回溯遞歸,每完成一趟就回到能再改變的位置。

package leetcode.problem22;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

class Solution3 {
    public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<>();
        solve(result,"",0,0,n);
        return result;
    }

    private void solve(List<String> result, String s, int start, int end, int n) {
        if (s.length() == 2 * n){
            result.add(s);
            return;
        }
        if (start < n){
            solve(result, s + "(",start + 1,end,n);
        }
        if (end < start){
            solve(result, s + ")",start,end + 1,n);
        }
    }
}

方法三

先是找左括號,每找到一個左括號,就在其後面加一個完整的括號,最後再在開頭加一個(),就形成了所有的情況,需要注意的是,有時候會出現重複的情況,所以用set數據結構,好處是如果遇到重複項,不會加入到結果中,最後再把set轉爲list即可。

n=1:    ()

n=2:    (())    ()()

n=3:    (()())    ((()))    ()(())    (())()    ()()()   
package leetcode.problem22;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

class Solution {
    public List<String> generateParenthesis(int n) {
        Set<String> result = new HashSet<>();
        if (n == 0){
            result.add("");
        }else {
            List<String> pre = generateParenthesis(n - 1);
            for (String string : pre){
                for (int i = 0; i < string.length(); i++) {
                    if (string.charAt(i) == '('){
                        result.add(string.substring(0, i + 1) + "()" + string.substring(i + 1 ));
                    }
                }
                result.add("()" + string);
            }
        }
        return new ArrayList<>(result);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章