Python 为什么这两种求第n个斐波那契数的算法中的一种更有效?

Python 为什么这两种求第n个斐波那契数的算法中的一种更有效?,python,algorithm,fibonacci,Python,Algorithm,Fibonacci,计算第64个斐波那契数时,第一个算法需要几个小时,第二个算法不到一秒钟 为什么第二种算法的效率比第一种算法高很多 他们看起来很相似 def fib_divide_recursion(n): if n <= 2: return n-1 else: return fib_divide_recursion(n-1) + fib_divide_recursion(n-2) def fib_linear_recursion(n, prev={}):

计算第64个斐波那契数时,第一个算法需要几个小时,第二个算法不到一秒钟

为什么第二种算法的效率比第一种算法高很多

他们看起来很相似

def fib_divide_recursion(n):
    if n <= 2:
        return n-1
    else:
        return fib_divide_recursion(n-1) + fib_divide_recursion(n-2)

def fib_linear_recursion(n, prev={}):
    if n <= 2:
        return n-1
    try:
        return prev[n]
    except KeyError:
        prev[n] = fib_linear_recursion(n - 1, prev) + 
            fib_linear_recursion(n - 2, prev)
        return prev[n]
def fib_divide_递归(n):

如果n则第一个算法的复杂度为O(2^n)

第二个函数将结果缓存在
prev
中,因此它不会对给定的数字多次计算
fib\u线性递归。它的复杂性是线性的,O(n)


有关更多详细信息,请参阅。

第二个实现是使用“记忆”来记住以前计算的斐波那契值


假设您正在尝试计算
fib(5)
:首先必须计算
fib(4)
fib(3)
fib(4)
本身也要求您计算
fib(3)
。事实上,对于每个斐波那契数,您可以计算前面的每个斐波那契数一次并存储它们(这是记忆方法)。或者,在性能差得多的情况下,您可以重新计算所需的每个斐波那契数,即使您以前已经计算过。显然,如果没有记忆,您将需要做指数级的更多工作,而对于高斐波那契数,正如您所观察到的,这确实会产生不同。

1算法只使用递归,而第2算法使用动态规划,即带记忆的递归


如果您为第一个算法绘制一棵树,您将看到重复的节点。但第二种算法存储的是已经计算过的节点,因此程序不必一次又一次地计算,因为第一种算法做的工作更多。计算它执行的函数调用次数。计算
fib\u divide\u递归(25)
调用函数150049次,计算
fib\u linear\u递归(25)
调用函数47次,随着
n
的增长,差异会迅速变大。除此之外,因为您正在使用递归作为最常见的迭代编程示例。@Klaus是的,但递归学习斐波那契也很有价值-事实上,这是递归程序最常见的介绍之一。@Klaus,我同意您的观点,但不幸的是,很难抵消先例的浪潮。无论如何,学习斐波那契对于理解递归与迭代的优缺点是很有用的,即使它并不理想,仅仅因为它的建立非常好。谢谢,为什么我不能使用prev=[]替换prev{},即使我将keyrerror改为indexertoo@longchaos真正地这是一个不同的问题,如果你想得到正确的答案,你应该单独发布。但简单的回答是列表不是字典:你不能索引到列表中还不存在的部分,并期望它被自动创建。您必须使用所需的元素数对其进行初始化,这是不可伸缩的。