使用递归的合法括号对的序列-Python

时间:2018-12-05 08:40:54

标签: python-3.x recursion recursive-backtracking

我在Python中使用递归需要解决一些问题。 我只是递归不好,不知道如何开始,所以请指导我。

  

如果字符串仅包含字符'(',')'并且可以以数学公式的方式写成这样的括号序列,那么我们将说一个字符串包含'n'个合法的括号对,括号的每次打开都会关闭,并且括号在打开之前不会关闭)。描述它的更精确方法是在字符串的开头,'('大于或等于')'的数目-整个字符串中任何类型的char的数目都相等。实现一个函数,该函数接收正整数n并返回一个列表,该列表包含括号中n组合的每个合法字符串。

我至少已经开始尝试,考虑了一个基本案例,但是我的基本案例到底是什么?

当给定最小n为1时,我试图考虑一个基本情况,然后我想我必须返回一个列表['(',')']。但是要做到这一点我也有困难...

 1 2 3 4
 1 2 3
 1 2
 1

请向我解释递归解决问题的方法。

谢谢!

1 个答案:

答案 0 :(得分:2)

看一个简单的问题案例可能会有所帮助:

n = 2
(())
()()

因此,我们从n=2开始,我们先产生(次n次序列,然后再产生)次n次序列,然后返回其列表。然后,我们以n-1递归地执行该操作。当我们到达n=1时,就好像到达了基本情况一样,就是我们需要返回一个() n次的字符串(不是n = 1而是n = 2)。

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

n=3相同的模式。

以上示例有助于理解如何递归解决问题。

def legal_parentheses(n, nn=None):
    if nn == 1:
        return ["()" * n]
    else:
        if not nn:
            nn = n

        # This will produce n ( followed by n ) ( i.e n=2 -> (()) )
        string = "".join(["(" * nn, ")" * nn])

        if nn < n:
            # Then here we want to produce () n-nn times.
            string += "()" * (n-nn)

        return [string] + legal_parentheses(n, nn-1)

print(legal_parentheses(3))
print(legal_parentheses(4))
print(legal_parentheses(5))

对于n = 3:

['((()))', '(())()', '()()()']

对于n = 4:

['(((())))', '((()))()', '(())()()', '()()()()']

对于n = 5:

['((((()))))', '(((())))()', '((()))()()', '(())()()()', '()()()()()']

这是解决问题的一种方式。

我认为,递归地解决问题的方法是首先选择您所遇到问题的最简单示例n=2,然后写下您的期望结果。在这种情况下,您期望获得以下输出:

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

现在,您正在尝试找到一种解决问题的策略,以便可以产生每个字符串。我首先考虑基本情况。我说微不足道的情况是当结果为()()时,我知道该结果的元素只是()的n倍。如果是n=2,我应该期望()(),而当n=3我应该期望()()()时,序列中应该只有一个这样的元素(因此应该只执行一次)因此,它成为基本情况。问题是我们如何计算结果的(())部分。这些模式表明,我们只需要在n后面加上( n,然后再加上) (())-> n=2。这看起来是个不错的策略。现在,您需要开始思考一个稍微棘手的问题,看看我们的策略是否仍然有效。

因此,让我们想到n=3。结果是什么?

'((()))', '(())()', '()()()'

好的,我们看到基本情况仍然应该产生()()()部分,也应该产生((()))部分。 (())()部分呢?看来我们需要稍微不同的方法。在这种情况下,我们需要以某种方式生成n (,然后生成n ),然后生成n-1 (,然后生成n-1 ),然后n-2 (之后是n-2 ),依此类推,直到达到基本情况n=1,在这里我们将只生产()部分{ {1}}次。但是,如果我们每次用n调用该函数,那么当我们到达基本情况时,我们不知道原始的n-1值是什么,因此我们无法产生n部分因为我们不知道要多少(如果原始()是3,那么我们需要n,但是如果我们通过用()()()调用函数来更改n,然后按当我们达到基本情况时,我们将不知道原始的n-1值)。因此,因此,在我的解决方案中,我引入了一个名为n的第二个变量,该变量每次都会减小,但仍然nn保持不变,因此我们知道< / strong>原始值是什么。