我正在学习递归函数中的记忆,偶然发现了Youtube上的fibonacci示例。我从未见过该人运行该代码,所以也许他写错了。
当我复制代码并尝试运行它时,由于我声明备忘录没有范围,所以我首先遇到了错误,所以我只是将范围设置为输入+ 1(因为我没有使用0索引)从而解决了这个问题。但是现在我陷入了错误的返回值。
def fib(num, memo=[]):
if num == 0:
return 0
elif num == 1 or num == 2:
return 1
elif memo[num] != None:
return memo[num]
else:
memo[num] = fib(num-1, memo) + fib(num-2, memo)
return memo[num]
uInput = int(input("Fibonacci: "))
memo = list(range(uInput + 1))
fibNum = fib(uInput, memo)
print(fibNum)
上面的代码没有引发任何错误,只是返回了“ uInput”值。因此,如果我为第六个斐波那契数字输入6,则程序将返回6而不是实际的第六个数字8。我不知道为什么会这样。
当我在问题上进行搜索时,我发现建议使用字典而不是列表的主题。如果那是唯一的方法,那就很好。但是,如果有一种方法可以使它与列表一起使用,我想了解如何完成此操作,以便理解为什么会遇到此问题。
答案 0 :(得分:1)
访问memo[num]
将永远不会返回None
。如果num
超出范围,将引发IndexError
。而且,您通常不希望将memo
参数传递给函数,而是让它依赖于自己的memo
对象。
在您的情况下,您要检查索引是否在len
的范围内。每当num
超出范围时,都必须递归计算并记录输出。只有这样才能将其退回。
def fib(num, memo=[0, 1]):
if num >= len(memo):
memo.append(fib(num - 1) + fib(num - 2))
return memo[num]
print(fib(10)) # 55
顺便说一句,上面的代码可以轻松转换为迭代函数,在Python中通常更有效。
def fib(num, memo=[0, 1]):
while num >= len(memo):
memo.append(memo[-1] + memo[-2])
return memo[num]
答案 1 :(得分:0)
您用memo
填充了list(range(uInput + 1))
列表。然后,您的函数将测试memo[num] != None
,这必须是正确的。因此,它总是执行return memo[num]
,从而返回由memo
函数放置在range
列表中的数字。
您应该删除此行
memo = list(range(uInput + 1))
,并且仅在调用函数时传递第一个参数。
答案 2 :(得分:0)
这里有错误:
memo = list(range(uInput + 1)) # wrong
对于尚未计算的每个结果memo
,None
应该在索引i
上包含fib(i)
:
memo = [None] * (uInput + 1) # right
该备忘录可以初始化为序列0,1的开头,这将简化功能:
def fib(num, memo):
if memo[num] is None:
memo[num] = fib(num-1, memo) + fib(num-2, memo)
return memo[num]
uInput = int(input("Fibonacci: "))
memo = [0,1] + [None]*uInput
fibNum = fib(uInput, memo)
print(fibNum)
更新:
原始代码中还有另一个错误:memo
是必需的参数,通常不能与默认值一起使用。
答案 3 :(得分:0)
我相信您的问题是一个很好的论证,为什么应将备忘录用作装饰器,而不是与函数本身交织在一起:
select replace(Address, 'TX', 'Texas') address
from Your_Table
where Address like '%TX%'
否则,您将尝试同时调试两个不同的程序。使用from functools import lru_cache
@lru_cache()
def fibonacci(number):
if number == 0:
return 0
if number == 1 or number == 2:
return 1
return fibonacci(number - 1) + fibonacci(number - 2)
uInput = int(input("Fibonacci: "))
fibNum = fibonacci(uInput)
print(fibNum)
装饰器和不使用装饰器,在输入100的情况下尝试上面的方法。
当然,由于Python调用堆栈的深度,这仍然仅限于相对较小的输入。有一些迭代(甚至更好的递归)算法可以做得更好。