Description

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

Example 1:

Input: n = 3 Output: [”((()))”,”(()())”,”(())()”,”()(())”,”()()()“]

Example 2:

Input: n = 1 Output: [”()“]

Constraints:

  • 1 <= n <= 8

Code

Backtracking

對於一組 parenthesis 而言,其是否 valid 的關鍵點在於 number of open brackets == number of closed brackets,其排列順序並不重要,不影響正確性。

Valid Parentheses 有三種 parentheses,所以必須用 stack 來檢查,像是 { ) 的組合就是 invalid 的,但是在這裡 () 就可以用 ( 數量為 1 以及 ) 數量也是 1 來檢查合法性。

注意遞迴的條件:open < n 以及 close < open,要先有 open 才可以有 close,而 open 只需要數量不超過一半即可,隨時想開都可以。

此重要觀察可以應用在 Check if a Parentheses String Can Be Valid

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> results;
        helper(0, 0, n, "", results);
        return results;
    }
 
    void helper(int open, int close, int n, string curr, vector<string> &results) {
        if(curr.length() == n * 2) {
            results.push_back(curr);
            return;
        }
        if(open < n) helper(open + 1, close, n, curr + "(", results);
        if(open > close) helper(open, close + 1, n, curr + ")", results);
    }
};

DP

Intuition:類似 Unique Binary Search Trees 的想法。

關鍵點在於新增 () 的方式,下面解法切成兩半,新增在左半邊(包起來),右邊放剩下可以放的數量。

n = 3 為例:(0) 2, (1) 1, (2) 0 ,其中 (0) 2 即是 () ()(), () (())(1) 1 即是 (()) ()(0) 2 即是 () (()), () ()()

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<vector<string>> answer(n + 1);
        answer[0] = {""};
 
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j < i; j++) {
                for(auto s1: answer[j]) {
                    for(auto s2: answer[i - 1 - j]) {
                        answer[i].emplace_back("(" + s1 + ")" + s2);
                    }
                }
            }
        }
        return answer[n];
    }
};

Source