如何使递归fib函数通过备注返回正确的值

时间:2019-04-28 19:11:37

标签: python recursion fibonacci memoization

我正在学习递归函数中的记忆,偶然发现了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。我不知道为什么会这样。

当我在问题上进行搜索时,我发现建议使用字典而不是列表的主题。如果那是唯一的方法,那就很好。但是,如果有一种方法可以使它与列表一起使用,我想了解如何完成此操作,以便理解为什么会遇到此问题。

4 个答案:

答案 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

对于尚未计算的每个结果memoNone应该在索引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调用堆栈的深度,这仍然仅限于相对较小的输入。有一些迭代(甚至更好的递归)算法可以做得更好。