【问题标题】:Nth Fibonacci in pythonpython中的第N个斐波那契
【发布时间】:2021-11-15 19:14:35
【问题描述】:
def fibonaci(i,memo):
    if i == 0 or i == 1:
       return i

    if memo[i]==-1:
       memo[i] = fibonaci(i-1,memo) + fibonaci(i-2,memo)

    return memo[i]

def fibo(n):
    a = []
    return fibonaci(n,a)

print(fibo(2))

我是一名学习 python 的 Java 程序员。该算法使用递归 + 记忆计算第 n 个斐波那契数。我不明白为什么在 python 中运行程序时会看到此错误“IndexError: list index out of range”。有人可以帮忙吗?非常感谢!

【问题讨论】:

  • 当某个项目不在您的备忘录列表中时,您希望发生什么?
  • 您的错误是索引空数组的结果。
  • 您能否评论一下您认为memo[i]==-1 何时为真?
  • 您正在传递空列表 'a' 并访问第三个元素 'memo[2]'
  • 我假设 python 中的 a = [ ] 等同于 Java 中的 new int[n] 。那么我必须先用 0 填充列表吗?

标签: python dynamic-programming


【解决方案1】:

美好的一天,欢迎使用 Python :-)

正如 cmets 对您的问题所建议的那样, memo[i]==-1 不可能是真的。

我知道您想测试“如果 fibonacci(i) 的值尚未被记忆”之类的东西,但是 Python 在 index 中告诉您的方式不存在肯定不是通过返回一些神奇的值(例如 - 1),而是通过引发异常。

在您最喜欢的搜索引擎上查找“EAFP”(请求宽恕比请求许可更容易)可能会告诉您为什么 Python 中的异常不应被理解为错误。

此外,记忆化最好通过字典而不是列表来实现(因为字典允许将值映射到任何可能的键,而不一定映射到下一个整数索引值)。

在不改变程序结构的情况下,我建议如下:

def fibonaci(i,memo):
    if i == 0 or i == 1:
        return i

    try:
        memo[i]
    except KeyError:
        memo[i] = fibonaci(i-1,memo) + fibonaci(i-2,memo)

    return memo[i]

def fibo(n):
    a = {} 
    return fibonaci(n,a)

print(fibo(2))

【讨论】:

  • 我们保存在列表中。所以我们需要直到 n-1 才能得到正确的第 n 个斐波那契数。所以应该return fibonaci(n-1,a)
  • 谢谢@Papa Alpha 哇,我以前从未听说过 EAFP。我今天学到了新东西!你的方法确实比使用列表好得多。再次感谢您
【解决方案2】:

我对您的代码进行了一些更改以获得第 n 个斐波那契数。(也可能有其他方式)

def fibonaci(i,memo):
    if i == 0 or i == 1:
       return i

    if memo[i] == -1:
       memo[i] = fibonaci(i-1,memo) + fibonaci(i-2,memo)

    return memo[i]

def fibo(n):
    a = [-1] * n
    return fibonaci(n-1,a)

print(fibo(5))
print(fibo(10))
print(fibo(13))
print(fibo(57))

输出是:-

3
34
144
225851433717

【讨论】:

  • 我知道这是一个非常琐碎的问题。不过,感谢您的帮助!
【解决方案3】:

您看到错误是因为您使用a = [] 创建了一个空列表,然后您尝试查看它。您需要创建一个足够长的列表来索引从零到 n-1。

话虽如此,在 Python 中进行记忆的一种简单方法是使用来自 functoolscache 函数。这段代码为你做记忆:

from functools import cache


@cache
def fib(n):
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)


for n in range(10):
    print(f"{fib(n) = }")

相当在运行时间上效率不高,但在程序员时间上却是。

【讨论】:

  • 很高兴知道有缓存功能!谢谢
  • 不客气。它对于快速而肮脏的动态编程非常有用。
猜你喜欢
  • 2022-12-10
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 1970-01-01
  • 2021-09-03
  • 2015-04-17
  • 2017-01-29
  • 1970-01-01
相关资源
最近更新 更多