在做Project Euler Problem 25时,我遇到了各种计算第n个Fibonacci数的技术。记忆似乎是其中最快的,直观地说,我期望记忆化比从下至上创建列表更快。
这两个函数的代码是:
def fib3(n): #FASTEST YET
fibs= [0,1] #list from bottom up
for i in range(2, n+1):
fibs.append(fibs[-1]+fibs[-2])
return fibs[n]
def fib4(n, computed= {0:0, 1:1}): #memoization
if n not in computed:
computed[n]= fib4(n-1, computed)+ fib4(n-2, computed)
return computed[n]
print fib3(1000)
print fib4(1000)
fib3比fib4快约8倍。我无法弄清楚这背后的原因。基本上两者都是在计算时存储值,一个在列表中,另一个在字典中,以便他们可以访问它们作为"缓存"后来。为什么会有巨大的差异?
答案 0 :(得分:0)
在thesonyman101上进行开发:my_list[i]
使您能够立即访问该元素,而my_dict[key]
需要计算哈希函数并在查看存储桶中的内容之前检查冲突。此外,您的memoization设置了一些潜在的深度递归堆栈,这也有一些成本。
更快(如果你不需要重新计算几个值,我知道Euler问题不是这样的话:)只是跟踪最后两个术语。所以你不会浪费任何列表管理费用。
答案 1 :(得分:-1)
您正在使用fib4函数中的递归。这在时间复杂度方面是指数
编辑后,有人说记忆使fib4线性化: 除了它没有。
记忆的东西只能减少重复呼叫的计算时间。数字n的斐波纳契值首次仅通过递归计算。
自己尝试一下
0.00010111480978441638
0.00039419570581368307
[Finished in 0.1s]
这将显示fib4需要更长时间。
print (min(timeit.Timer('fib3(600)', setup=setup).repeat(3, 100)))
print (min(timeit.Timer('fib4(600)', setup=setup).repeat(3, 100)))
如果更改最后两行,即每次重复100次,结果会发生变化现在,fib4变得更快,好像不仅没有递归,几乎没有额外的时间来计算
0.00501430622506104
0.00045805769094068097
[Finished in 0.1s]
50次重复的结果
0.01583016969421893
0.0006815746388851851
[Finished in 0.2s]
100次重复的结果
pair_count = df.mapPartitions(lambda iterable: pair_func_cnt(iterable))
pair_count.collection()
答案 2 :(得分:-2)
正如您所看到的,斐波那契算法(带递归)的复杂性约为O(2 ^ n)。
而对于fib3
,它将是O(n)。
现在您可以计算,如果您的输入大小为3,fib3
将具有O(3)的复杂度,但fib4
将具有O(8)。
你可以看到,为什么它会变慢。