生成括号

题目描述:给定 n 对括号,请写一个函数以将其生成新的括号组合,并返回所有组合结果。

样例:

给定 n = 3, 可生成的组合如下: "((()))", "(()())", "(())()", "()(())", "()()()"

这道题就有些难度了。

想一想这种生成括号的规则,其实隐含了一条信息:那就是始终左括号的数量要大于或等于右括号的数量。也就是说,剩余的左括号的数量要始终小于等于右括号。左括号只要有,就可以打印;而只有当剩余的右括号数量比左括号大时,才能打印右括号。为了方便理解,我现在假设n = 2,那么根据刚才我说的隐含信息,逻辑应该是这样的:

1. 肯定要先取一个左括号,此时左括号剩余的数量变为1,右括号剩余数量还是2

2. 第二位取左括号也行,取右括号也行。如果取左括号,那么此时右括号剩余数量为2,左括号剩余数量为0,长成了这个样子"((";如果取右括号,左右剩余数量都是1,长成这个样子"()"

3. 第三位,如果剩余左括号没了,就只能跟进右括号了,连续两个,最终变成"(())";而如果现在是"()"的,那么要先左后右,最终变成"()()".

发现,每一步都有两种选择:左或者右,当然不一定都可行,如果可行,那么往后继续,不可行,终止。

这是什么,二叉树。对于n = 2的情况,他的二叉树应该是这样的:



这棵二叉树表达的东西其实跟我刚才说的是一样的,而我们所要的结果就是这棵二叉树遍历所有路径的结果。由此,不妨先来回忆一下之前“二叉树的所有路径”这道题目(详见:点击打开链接)可以仿照这个方法来解决我们当前的问题。所不同的是,这里我们没有一棵已经给出的二叉树,但是,此处,我们相当于知道了这棵二叉树的左右节点是否为空的条件(就是一开始的隐含信息,左括号要始终大于等于右括号,也就是说剩余的左括号要始终小于等于剩余的右括号),以及不为空时,节点的值(左括号为"(",右括号为")")。

那么可以尝试给出代码了:

class Solution:
    # @param {int} n n pairs
    # @return {string[]} All combinations of well-formed parentheses
    def generateParenthesis(self, n):
        result = []
        path = ""
        self.helper(n, n, path, result)
        return result
    
    # left和right为判断节点是否存在提供依据
    def helper(self, left, right, path, result):
        # 相当于节点为空,也就是深搜不能再深入了
        if left == right == 0:
            result.append(path)
        # 相当于左节点存在
        if left > 0:
            self.helper(left - 1, right, path + "(", result)
        # 相当于右节点存在
        if right > left:
            self.helper(left, right - 1, path + ")", result)
        # Write your code here

其中,left和right为剩余的左右括号的数量

该问题和《编程之美》的买票找零问题是一样的(2n个人买东西,价格是50,其中n个人只带了50元面钞,另外n个人只带了100,卖家没零钱,问怎样能找开),感兴趣的话,可以去了解一下

如果觉得还不能理解,可以看看我的博文“二叉树的所有路径”,链接刚才给了。对照那个里面的代码,再理解一下。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值