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

[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

[中文翻译]
给定n对括号,写一个函数生成所有合法的组合。

例如,给定n = 3,解集是:

[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

[解题思路]
有两种想法,一种是先枚举出用’(‘或’)’构成长度为2n的字符串的所有可能,一共有22n,然后对于每一种可能,去判断一下是否合法,然后获得所有合法的可能。另一种自然的想法是使用递归,我采用的是递归的解法。

关于什么是递归,为什么会想到使用递归,这里就不细讲了。因为递归这种思想,对初学者而言有点难,对已经入门的却又很自然。建议初学者单步调试一下递归的代码,具体看一下执行过程中那些变量是什么样的,这样或许容易理解递归究竟是怎么递归下去的,又是怎么回溯上来的。

我这里设计的递归函数如下:

void generateParenthesisRecursively(vector<string>& res, int leftQuote, int rightQuote, int n, string s);
  • res是最后的结果,作为引用传入,也可以设成一个全局变量。
  • leftQuote是当前字符串s中已有的左括号个数。
  • rightQuote是当前字符串s中已有的右括号个数。
  • n是题目中输入的n,也可以改成全局变量。
  • s是当前递归到的字符串。

递归其实就是有条理地在进行状态搜索。

先判断一下当前的字符串s是否是一个合法的括号组合。
如果当前s中leftQuote=rightQuote=n,那么说明当前的s已经是一个合法的括号组合,可以将它加入res。而且在s的基础上再继续添加任何字符都不可能构成其他的合法字符,所以不需要继续递归下去。这是递归的终结点。

if (leftQuote == rightQuote && leftQuote == n) {
    res.push_back(s);
    return;
}

如果s还不是一个合法的括号组合,那么可以在s的基础上扩展一个’(‘或’)’。
只要leftQuote<n,就可以扩展一个’(‘,以s+’(‘为前缀的字符串可能成为一个合法括号匹配,因此需要继续递归。

if (leftQuote < n)
    generateParenthesisRecursively(res, leftQuote + 1, rightQuote, n, s + "(");
}

如果leftQuote>rightQuote,就可以扩展一个’)’,以s+’)’为前缀的字符串可能成为一个合法括号匹配,因此需要继续递归。

if (leftQuote > rightQuote)
    generateParenthesisRecursively(res, leftQuote, rightQuote + 1, n, s + ")");

这样的一个递归,不会有漏掉没有搜索的状态,因为它保证了所有可能构成合法括号组合的前缀s都会被搜索到。同时,它又不会永无止境地递归下去,因为leftQuote<n和leftQuote>rightQuote两个继续递归的条件保证了最终一定会达到leftQuote=rightQuote=n,而这是一个终结状态。

补充一点,这里实际上(leftQuote, rightQuote, s)构成了递归的状态,s控制了结果,leftQuote和rightQuote控制了递归的方向和递归的停止。实际上,用这三个变量来表示状态,是有多余的,只是为了便于理解。

[C++代码]

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> result;

        generateParenthesisRecursively(result, 0, 0, n, "");

        return result;
    }
    void generateParenthesisRecursively(vector<string>& res, int leftQuote, int rightQuote, int n, string s) {
        if (leftQuote == rightQuote && leftQuote == n) {
            res.push_back(s);
            return;
        }

        if (leftQuote < n)
            generateParenthesisRecursively(res, leftQuote + 1, rightQuote, n, s + "(");

        if (leftQuote > rightQuote)
            generateParenthesisRecursively(res, leftQuote, rightQuote + 1, n, s + ")");
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值