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的所有二进制代码。
答案 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
设置为['']
,现在我们迭代该列表的每个元素,但首先,我们定义一个空列表lst
。 small
只有一个元素''
。因此,我们将两个元素附加到lst
:'' + '0'
(仅'0'
),同样'1'
。
然后我们返回列表。现在我们知道codes(1)
会返回['0', '1']
。让我们回到执行codes(2)
codes(2)
(续) small
被分配了codes(1)
的结果,我们现在知道它是['0', '1']
。现在我们再次初始化一个空列表lst
,并迭代small
。对于small
中的每个元素(我们有两个),我们将两个元素追加到lst
:这意味着0
我们追加0
和1
来获取00
和01
以及1
相同,以获取10
和11
。
codes(2)
会返回['00', '01', '10', '11']
。通常,您会看到codes(n)
结果中的每个元素,codes(n+1)
将返回两个元素:分别附加0
和1
的元素。因此,返回列表的长度总是加倍,应该是。
重要的是要理解尽管名称small
和lst
是固定的,但它们在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字符串后,就会有一个更长字符串的列表。您可以将此结果传递给任何要求它的人(可能是您自己,尝试使甚至更长的字符串)。