这个递归二进制代码功能如何工作?

时间:2016-01-30 21:05:22

标签: python recursion

def codes(r):
  '''(int) -> list of str

  Return all binary codes of length r.

  >>> binary_codes(2)
  ['00', '01', '10', '11']
  '''
  if r == 0:
    return ['']
  small = codes(r-1)
  lst = []
  for item in small:
    lst.append(item + '0')
    lst.append(item + '1')
  return lst

目前正在学习递归,并对此函数的确切运作方式感到困惑。它应该返回一个长度为r的二进制代码字符串列表(根据docstring),使用你可以为每个二进制代码添加0和1的知识。获得下一个字符串的数量。

现在我感到困惑的是小=代码(r-1)部分

如果我追踪到这一点,似乎只是不断地调用该函数,直到' r == 0'是真的,在那种情况下,它最终返回空?将0和1添加到空列表中似乎只会给你[' 0',' 1']。该函数如何使用该基本情况设法返回长度为r的所有二进制代码。

2 个答案:

答案 0 :(得分:3)

让我们看一下r = 2:

codes(2)

r不为0,所以我们不返回任何内容。 small获得了codes(1)的返回值。所以要继续,我们必须先看看codes(1)首先返回的内容。

codes(1)

同样,r不为0.因此此调用中的small设置为codes(0)。我们必须查看codes(0)返回的内容。

codes(0)

这是硬编码返回['']。让我们回到执行codes(1)

codes(1)(续)

small设置为[''],现在我们迭代该列表的每个元素,但首先,我们定义一个空列表lstsmall只有一个元素''。因此,我们将两个元素附加到lst'' + '0'(仅'0'),同样'1'

然后我们返回列表。现在我们知道codes(1)会返回['0', '1']。让我们回到执行codes(2)

codes(2)(续)

small被分配了codes(1)的结果,我们现在知道它是['0', '1']。现在我们再次初始化一个空列表lst,并迭代small。对于small中的每个元素(我们有两个),我们将两个元素追加到lst:这意味着0我们追加01来获取0001以及1相同,以获取1011

因此,codes(2)会返回['00', '01', '10', '11']

通常,您会看到codes(n)结果中的每个元素,codes(n+1)将返回两个元素:分别附加01的元素。因此,返回列表的长度总是加倍,应该是。

重要的是要理解尽管名称smalllst是固定的,但它们在codes的每个调用中引用不同的对象,我想这可能是你的原因混乱。

答案 1 :(得分:1)

递归函数的关键是知道何时退出!每个递归函数,或者一组相互递归函数中的至少一个成员,都会有一个简单的测试,“这是结尾,或者开始,或者是底部或顶部的结果,因此结果是常量,空字符串,空列表或其他任何内容。“

<强>终止

您的终止条件为r == 0。当要求所有长度为零的二进制字符串时,您将返回[''] - 包含空字符串的列表。为什么?因为没有这样的字符串,但是为了制作更长的字符串(见下文),我们需要一个字符串来追加。

<强>迭代

如果不在“这是结束”的情况下,递归函数需要在此过程中计算“再多一步”。由于函数的终止条件基于字符串的长度,因此迭代条件可能也基于字符串长度。在这种情况下,您可以通过缩短字符串来递归。所以你通过缩短(缩短)字符串来迭代。

如果您有一个像'0'这样的二进制字符串,那么所有可能的二进制字符串是什么长度比一个字符长?好吧,它们要么是['01','00']还是['10','00'],这取决于你是想在结束时还是在开头做更长的字符串。

那么如何制作长度为N的二进制字符串列表呢?好吧,首先你得到每个可能的长度为N-1 的二进制字符串,然后为每个字符串创建两个字符串,其中包含零或一个。

如何获得每个可能的长度为N-1 的二进制字符串?您可以调用此函数codes(N-1),它将返回它们。别担心怎么做!

所以small = codes(r-1)是你的函数,它获取一个字符短的字符串列表 - r-1部分。然后你迭代每一个,然后做两个!一个是字符串加'0',第二个是字符串加'1'。迭代完所有small -er字符串后,就会有一个更长字符串的列表。您可以将此结果传递给任何要求它的人(可能是您自己,尝试使甚至更长的字符串)。