首页 > 代码库 > [C++]LeetCode: 84 Generate Parentheses (卡特兰数)

[C++]LeetCode: 84 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:

"((()))", "(()())", "(())()", "()(())", "()()()"

思路:

所有组合的个数C是一个卡特兰数。

技术分享

用更小的C去求解组合的所有可能性。我们来看下具体如何解决。一般采用递归的方法,这样可以归结为子问题去解决。在每个递归函数中记录左括号的数量和可以加入的右括号的数量,然后每次都有两种选择,一个是放入左括号,一个是放入右括号。不过这些是有附加条件的,左括号的数量要大于0,可以加入的右括号的数量也要大于0(保证结果是合法的)。递归结束条件是,左右括号数量都为0。

Attention:

1. 设计巧妙,要保证结果的合法性,必须保证左括号的数量>0 (添加左括号);采用可被添加的右括号数量(左括号数量>右括号数量)

<span style="font-size:14px;">//根据剩余左括号的数量,以及可以添加的右括号的数量,来遍历所有的可能, 只要两者不为零,都会进行两次选择(遍历两个分叉)
        if(m > 0) { generateParenthesis_helper(ret, str + ")", n, m-1); }
        if(n > 0) { generateParenthesis_helper(ret, str + "(", n-1, m+1); }</span>
2. 这道题准确来讲,不涉及回溯的问题,我们只是遍历一个合法的二叉树(符合括号构成原则),并且打印所有的结果。所以不需要pop_back()添加进去的结果。因为我们是带着条件去go_deeper的,并且合法情况下,总是有两个选择。

可以试着画一个n = 2的遍历结果来加深理解。

技术分享

复杂度:O(结果的数量)。 

AC Code:

<span style="font-size:14px;">class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> ret;
        if(n <= 0) return ret;
        generateParenthesis_helper(ret, "", n, 0);
        return ret;
    }

private:
    void generateParenthesis_helper(vector<string>& ret, string str, int n, int m)
    {
        if(n == 0 && m == 0)
        {
            ret.push_back(str);
            return;
        }
        
        //根据剩余左括号的数量,以及可以添加的右括号的数量,来遍历所有的可能, 只要两者不为零,都会进行两次选择(遍历两个分叉)
        if(m > 0) { generateParenthesis_helper(ret, str + ")", n, m-1); }
        if(n > 0) { generateParenthesis_helper(ret, str + "(", n-1, m+1); }
    }
};</span>



[C++]LeetCode: 84 Generate Parentheses (卡特兰数)