我有以下片段,通过在“?”的位置更改0和1来精美地生成二进制数字。但我不明白这段代码是如何工作的。特别是 str_list [idx] =“?”这一行。为什么是“?”开始在idx位置恢复。
在编写递归时应该如何考虑这个?
这是代码
def gen_bin(str_list):
if "?" not in str_list:
print "".join(str_list)
return
idx = str_list.index("?")
gen_bin(str_list[:idx] + ["0"] + str_list[idx+1:])
gen_bin(str_list[:idx] + ["1"] + str_list[idx+1:])
str_list[idx] = "?"
gen_bin(list("1??"))
关于如何编写这种递归函数的任何建议都会帮助我变得更好。
感谢您的时间。
答案 0 :(得分:3)
函数gen_bin()
只是在输入参数列表中查找?
的第一个匹配项,使用以下行:
idx = str_list.index("?")
然后只在该位置插入0
,并以新列表作为新参数递归运行:
gen_bin(str_list[:idx] + ["0"] + str_list[idx+1:])
然后在那里插入1
并再次递归运行:
gen_bin(str_list[:idx] + ["1"] + str_list[idx+1:])
如果?
中没有str_list
,则只打印出参数。
该行:
str_list[idx] = "?"
是不必要的,完全没有,你可以观察到运行以下代码:
def gen_bin(str_list):
if "?" not in str_list:
#print "".join(str_list)
return
idx = str_list.index("?")
gen_bin(str_list[:idx] + ["0"] + str_list[idx+1:])
gen_bin(str_list[:idx] + ["1"] + str_list[idx+1:])
print str_list
str_list[idx] = "?"
print str_list
gen_bin(list("1??"))
返回:
['1', '0', '?']
['1', '0', '?']
['1', '1', '?']
['1', '1', '?']
['1', '?', '?']
['1', '?', '?']
答案 1 :(得分:3)
递归定义有两个部分:
终止条件。这部分很关键,经常首先出现。终止条件是你测试知道你是否“完成”。
通常,递归函数具有某种“自然”终止条件。例如,当您返回到1时,Fibonacci序列结束。当您返回到1时,Factorials结束。当您获得空列表时,列表处理结束。字符串处理以空字符串结尾。
无论是什么,任何递归函数都会失败 - 通常通过无限循环或递归直到发生堆栈溢出 - 除非您正确定义了终止条件,并且检查它是否成功。
出于这个原因,大多数递归函数看起来像这样:
def recursive_func(arg):
if terminating_condition(arg):
return simplest_value
# more code here
recursive_func(reduced_form(arg))
递归关系。一旦检查(并且失败)终止条件的测试,就必须调用递归关系。通常,这意味着执行涉及稍微较小形式的相同递归函数的计算。
示例:
N! := n *(n-1)!
fib(n):= fib(n-1)+ fib(n-2)
len(head:tail):= 1 + len(tail)
真实世界示例
让我们来看看你的例子:
def gen_bin(str_list):
if "?" not in str_list:
print "".join(str_list)
return
idx = str_list.index("?")
gen_bin(str_list[:idx] + ["0"] + str_list[idx+1:])
gen_bin(str_list[:idx] + ["1"] + str_list[idx+1:])
str_list[idx] = "?"
gen_bin(list("1??"))
很明显,这个功能遵循经典结构。第一段是对终止条件的测试。在这种情况下,终止条件是没有'?'在要替换的字符串中。
该函数的其余部分专用于递归关系。在这种情况下,它包括替换第一次出现的'?'在字符串中带有'0'或'1'并递归。
我认为这不是很好的代码。首先,最后的作业str_list[idx] = "?"
没有做任何事情。我怀疑这段代码最近被修改过了。它可能会编辑str_list
,直接将“0”和“1”设置为str_list[idx]
,而不是使用切片。
更重要的是,这不是一个好的代码,因为它只是打印结果。如果它返回二进制字符串列表而不是尝试打印它们,那将是一个更好的功能。