斐波那契数列
1、斐波那契数列
def fib(n): if n == 1 or n == 0: return 1 else: return fib(n-2)+fib(n-1) print([fib(n) for n in range(10)])
输出结果:[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
2、如果改为40个数的斐波那契
from time import time def fib(n): if n == 1 or n == 0: return 1 else: return fib(n-2)+fib(n-1) start = time() print([fib(n) for n in range(40)]) end = time() print("cost-time:{}".format(end-start))
运行结果:cost-time:131.5741560459137
光40位居然花费了131秒,50位就更长了.难是因为这个运算量太大了吗,NONONO,是因为我们算法没有经过优化.
-
看上面这张图,你会发现我们在计算兔子序列的时候,有大量重复的计算,比如算F(10)=F(9)+F(8),F(9)=F(8)+F(7),F(8)需要重复计算两次~~
-
怎么破,很容易想到我们需要用一个缓存,把这个计算过的数字存在一个表里面,用的时候若这个数字在这个表,就不用再花cpu去运算,直接取就好了。
我们现在构造一个缓冲区cache
我们查表,比如用字典来保存,比如cache[8]=34,我们只需要查一下8是不是在字典里面就可以了,在的话直接取,不在的话再去用算法计算,是不是很爽
from time import time def fib(n, cache=None): if cache is None: cache = {} if n in cache: return cache[n] if n == 1 or n == 0: return 1 else: cache[n] = fib(n-2, cache) + fib(n-1, cache) return cache[n] start = time() print([fib(n) for n in range(40)]) end = time() print("cost-time:{}".format(end-start))
运行结果:cost-time:0.0009999275207519531
看运行40项,几乎不费吹灰之力,这就是算法的魅力。
基于装饰器来实现
from time import time def decorate(func): cache = {} def wraper(n): if n not in cache: cache[n] = func(n) return cache[n] return wraper @decorate def fib(n): if n == 1 or n == 0: return 1 else: return fib(n - 2) + fib(n - 1) start = time() print([fib(n) for n in range(400)]) end = time() print("cost-time:{}".format(end - start))
===============================================================
基于yield来实现更加简单、高效。
import time def fab(num): n, a, b = 0, 0, 1 while n < num: yield b a, b = b, a + b n += 1 start_time = time.time() yield_fab = list(fab(400)) stop_time = time.time() - start_time >>>print(yield_fab) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610... >>>print(stop_time) 0.0039997100830078125