python - Fibonacci计算时差

时间:2016-04-13 11:25:53

标签: python python-3.x recursion fibonacci

我编写了以下两个用于计算Fibonacci序列元素的代码。

def fib(n):
    zero, one = 0, 1
    k = 1
    while k < n:
        zero, one = one, zero + one
        k = k + 1
    return one, ls

def fib2(n, memo=None):
    if memo is None:
        memo = {}
    if n == 1 or n == 2:
        return 1
    if n in memo:
        return memo[n]
    else:
        memo[n-1] = fib2(n-1, memo)
        memo[n-2] = fib2(n-2, memo)
        return memo[n-1] + memo[n-2]


##import timeit
##
##print('Fibonacci 1:', timeit.timeit('fib(10000)', '''def fib(n):
##    zero, one = 0, 1
##    k = 1
##    while k < n:
##        zero, one = one, zero + one
##        k = k + 1
##    return one''', number=100))
##
##print('Fibonacci 2:', timeit.timeit('fib2(10000)', '''import sys; sys.setrecursionlimit(10001);
##def fib2(n, memo=None):
##    if memo is None:
##        memo = {}
##    if n == 0 or n == 1:
##        return 1
##    if n in memo:
##        return memo[n]
##    else:
##        memo[n-1] = fib2(n-1, memo)
##        memo[n-2] = fib2(n-2, memo)
##        return memo[n-1] + memo[n-2]''', number=100))

我在while中使用了一个简单的fib循环,而fib2是一个递归的实现。{但事实证明fib2特别慢。我想知道它为什么。是因为fib2创建了大量的帧吗?我是否正确实施了fib2

感谢。

1 个答案:

答案 0 :(得分:1)

将此简化的递归版本与原始迭代解决方案相对应 - 首先将递归限制提高约1%至10%:

def fib2(n, memo={0: None, 1: 1, 2: 1}):
    if n in memo:
        return memo[n]

    previous = fib2(n - 1)  # implicitly computes fib2(n - 2)

    result = memo[n] = previous + memo[n - 2]

    return result

我没有通过memo作为递归的论据,因为我正在利用&#34;问题&#34;当默认参数设置为可以修改的结构时。

上述解决方案比第一次调用时我的机器上的原始迭代解决方案慢4.5倍 - 之后,memoization接管。我们可以在空间和空间上对此进行一点改进。时间,通过改变我们的记忆&#34;从字典到列表,因为所有键都是连续的整数:

def fib3(n, memo=[None, 1, 1]):
    if n < len(memo):
        return memo[n]

    previous = fib3(n - 1)  # implicitly computes fib3(n - 2)

    result = previous + memo[-2]

    memo.append(result)

    return result

在我的机器上,第一次调用比迭代解决方案慢〜3倍。但是,我们可以使用递归更快速地做到:

def fib4(n, res=0, nxt=1):
    if n == 0:
        return res
    return fib4(n - 1, nxt, res + nxt)

这比迭代解决方案慢〜2倍和/但没有记忆。在使用尾调用优化的语言(即不是Python)中,这可能会成为/ tie迭代。