天真递归快于记忆递归

问题描述

我是python的初学者,并且正在观看this视频以学习动态编程。 对于查找斐波那契数列的情况,导师介绍了备忘录,以提高递归算法的性能。 完整的代码如下

    import time

def fibonacci1(n):
    '''This uses the naive fibonacci algorithm. '''
    if n < 2:
        return n
    else:
        return fibonacci1(n-1) + fibonacci1(n-2)

def fibonacci2(n):
    ''' This function uses a memo of computed values to speed up the process'''
    memo = {}
    if n in memo:
        return memo[n]
    if n < 2:
        return n
    f = fibonacci2(n-1) + fibonacci2(n-2)
    memo[n] = f
    return f

def screen(i,N):
    if i==1:
        return fibonacci1(N)
    if i == 2:
        return fibonacci2(N)

N = int(input("Enter a number: "))

for i in range(2):
    t0 = time.time()
    fib = screen(i+1,N)
    print("The "+ str(N) +"th fibonacci number is {}".format(fib))
    t1 = time.time()
    print("Time taken is : {}s".format(t1-t0))

但这是我收到的输出FibonacciOutput

有人可以帮我吗?

解决方法

这里发生的是您的memo是一个局部变量,您正在fibonacci2的每次运行开始时向其分配一个空dict。因此,您将永远不会在n内找到memo

有多种方法可以完成您想做的事情。其中之一(不是最大的,但至少易于理解)正在使用全局变量:

memo = {}
def fibonacci2(n):
    ''' This function uses a memo of computed values to speed up the process'''
    global memo
    if n in memo:
        return memo[n]
    if n < 2:
        return n
    f = fibonacci2(n-1) + fibonacci2(n-2)
    memo[n] = f
    return f

在这里,我们在函数外部定义了memo,因此只定义了一次。 global memo行表示我们在函数中使用的memo实际上是在函数外部定义的。

,

根据您的代码:

    memo = {}
    if n in memo:

n怎么可能在您之前创建空的字典中出现?

我会这样:

def fibonacci2(n,memo={}):
    ...
,

似乎每次调用fibonacci2都会将备忘录重置为空字典。因此,这增加了执行dict读写的开销,但实际上并未向该算法添加备忘录。如果仅将memo = {}向上移动几行,以便其值保持不变,那么它似乎会有所帮助。

,

memo = {}函数外部声明fibonacci2(n)为全局变量 变量,因为当您在fibonacci2()内声明备忘录时,在调用函数时它将始终初始化为空。您可以这样

memo = {}
def fibonacci2(n):
    ''' This function uses a memo of computed values to speed up the process'''
   
    if n in memo:
        return memo[n]
    if n < 2:
        return n
    f = fibonacci2(n-1) + fibonacci2(n-2)
    memo[n] = f
    return f