[LeetCode] Generate Parentheses 生成括號

Grandyang發表於2015-04-21

 

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:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]
  

在LeetCode中有關括號的題共有三道,除了這一道的另外兩道是 Valid Parentheses 驗證括號 Longest Valid Parentheses 最長有效括號,這道題給定一個數字n,讓生成共有n個括號的所有正確的形式,對於這種列出所有結果的題首先還是考慮用遞迴Recursion來解,由於字串只有左括號和右括號兩種字元,而且最終結果必定是左括號3個,右括號3個,所以我們定義兩個變數left和right分別表示剩餘左右括號的個數,如果在某次遞迴時,左括號的個數大於右括號的個數,說明此時生成的字串中右括號的個數大於左括號的個數,即會出現')('這樣的非法串,所以這種情況直接返回,不繼續處理。如果left和right都為0,則說明此時生成的字串已有3個左括號和3個右括號,且字串合法,則存入結果中後返回。如果以上兩種情況都不滿足,若此時left大於0,則呼叫遞迴函式,注意引數的更新,若right大於0,則呼叫遞迴函式,同樣要更新引數。程式碼如下:

 

C++ 解法一:

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> res;
        generateParenthesisDFS(n, n, "", res);
        return res;
    }
    void generateParenthesisDFS(int left, int right, string out, vector<string> &res) {
        if (left > right) return;
        if (left == 0 && right == 0) res.push_back(out);
        else {
            if (left > 0) generateParenthesisDFS(left - 1, right, out + '(', res);
            if (right > 0) generateParenthesisDFS(left, right - 1, out + ')', res);
        }
    }
};

 

Java 解法一:

public class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<String>();
        helper(n, n, "", res);
        return res;
    }
    void helper(int left, int right, String out, List<String> res) {
        if (left < 0 || right < 0 || left > right) return;
        if (left == 0 && right == 0) {
            res.add(out);
            return;
        }
        helper(left - 1, right, out + "(", res);
        helper(left, right - 1, out + ")", res);
    }
}

 

再來看那一種方法,這種方法是CareerCup書上給的方法,感覺也是滿巧妙的一種方法,這種方法的思想是找左括號,每找到一個左括號,就在其後面加一個完整的括號,最後再在開頭加一個(),就形成了所有的情況,需要注意的是,有時候會出現重複的情況,所以我們用set資料結構,好處是如果遇到重複項,不會加入到結果中,最後我們再把set轉為vector即可,參見程式碼如下::

n=1:    ()

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

n=3:    (()())    ((()))    ()(())    (())()    ()()()   

 

C++ 解法二:

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        set<string> t;
        if (n == 0) t.insert("");
        else {
            vector<string> pre = generateParenthesis(n - 1);
            for (auto a : pre) {
                for (int i = 0; i < a.size(); ++i) {
                    if (a[i] == '(') {
                        a.insert(a.begin() + i + 1, '(');
                        a.insert(a.begin() + i + 2, ')');
                        t.insert(a);
                        a.erase(a.begin() + i + 1, a.begin() + i + 3);
                    }
                }
                t.insert("()" + a);
            }
        }
        return vector<string>(t.begin(), t.end());
    }
};

  

Java 解法二:

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

 

類似題目:

Remove Invalid Parentheses

Different Ways to Add Parentheses

Longest Valid Parentheses

Valid Parentheses

 

參考資料:

https://leetcode.com/problems/generate-parentheses/

https://discuss.leetcode.com/topic/4485/concise-recursive-c-solution

https://discuss.leetcode.com/topic/30026/2ms-ac-java-solution-using-recursive-call/2

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章