python的递归算法学习(2):具体实现:斐波那契和其中的陷阱
1.斐波那契
什么是斐波那契,斐波那契额就是一个序列的整数的排序,其定义如下;
Fn = Fn-1 + Fn-2
with F0 = 0 and F1 = 1
也就是,0,1,1,2,3,5,8,13.。。。。
递归实现:
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
非递归实现:
def fibi(n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a
在这里,我们如果仔细调试,会发现,递归实现,会消耗更多的时间,这里测试如下:
from timeit import Timer
from fibo import fib t1 = Timer("fib(10)","from fibo import fib") for i in range(1,41):
s = "fib(" + str(i) + ")"
t1 = Timer(s,"from fibo import fib")
time1 = t1.timeit(3)
s = "fibi(" + str(i) + ")"
t2 = Timer(s,"from fibo import fibi")
time2 = t2.timeit(3)
print("n=%2d, fib: %8.6f, fibi: %7.6f, percent: %10.2f" % (i, time1, time2, time1/time2))
结果如下;
C:\Python35\python.exe C:\pylearn\bottlelearn\fibnaqie.py
n= 1, fib: 0.000002, fibi: 0.000003, percent: 0.55
n= 2, fib: 0.000002, fibi: 0.000003, percent: 0.73
n= 3, fib: 0.000003, fibi: 0.000003, percent: 1.20
n= 4, fib: 0.000005, fibi: 0.000003, percent: 1.80
n= 5, fib: 0.000007, fibi: 0.000003, percent: 2.45
n= 6, fib: 0.000012, fibi: 0.000004, percent: 3.31
n= 7, fib: 0.000022, fibi: 0.000003, percent: 6.50
n= 8, fib: 0.000030, fibi: 0.000004, percent: 8.38
n= 9, fib: 0.000049, fibi: 0.000003, percent: 14.58
n=10, fib: 0.000078, fibi: 0.000004, percent: 20.07
n=11, fib: 0.000126, fibi: 0.000004, percent: 35.00
n=12, fib: 0.000203, fibi: 0.000004, percent: 52.29
n=13, fib: 0.000330, fibi: 0.000004, percent: 79.20
n=14, fib: 0.000537, fibi: 0.000004, percent: 120.94
n=15, fib: 0.000925, fibi: 0.000005, percent: 196.18
n=16, fib: 0.001693, fibi: 0.000007, percent: 244.16
n=17, fib: 0.007242, fibi: 0.000011, percent: 652.70
n=18, fib: 0.004422, fibi: 0.000007, percent: 637.64
n=19, fib: 0.010322, fibi: 0.000008, percent: 1240.40
n=20, fib: 0.010813, fibi: 0.000007, percent: 1443.78
n=21, fib: 0.025547, fibi: 0.000011, percent: 2246.24
n=22, fib: 0.035421, fibi: 0.000011, percent: 3192.22
n=23, fib: 0.060877, fibi: 0.000008, percent: 7837.86
n=24, fib: 0.090561, fibi: 0.000007, percent: 12091.41
n=25, fib: 0.132058, fibi: 0.000008, percent: 16415.97
n=26, fib: 0.227813, fibi: 0.000008, percent: 29330.54
n=27, fib: 0.557644, fibi: 0.000014, percent: 38659.17
n=28, fib: 0.578976, fibi: 0.000009, percent: 65224.25
n=29, fib: 1.133326, fibi: 0.000008, percent: 140882.03
n=30, fib: 1.454107, fibi: 0.000009, percent: 169095.94
n=31, fib: 2.274395, fibi: 0.000009, percent: 264486.10
n=32, fib: 3.817956, fibi: 0.000009, percent: 430110.09
n=33, fib: 5.923710, fibi: 0.000009, percent: 688859.58
n=34, fib: 9.629423, fibi: 0.000009, percent: 1020986.44
n=35, fib: 15.910085, fibi: 0.000009, percent: 1686911.18
n=36, fib: 26.556680, fibi: 0.000009, percent: 2901071.88
n=37, fib: 43.014073, fibi: 0.000016, percent: 2673506.31
为什么会这样呢?我们思考一下,递归过程的计算数,具体如下;

从树中可以看到,有重复计算的情况,(f(1)就计算了很多次。
在这里,尝试做一个改进,引入一个临时的字典,把计算过的内容做一个保存:
memo = {0:0, 1:1}
def fibm(n):
if not n in memo:
memo[n] = fibm(n-1) + fibm(n-2)
return memo[n]
重新进行时间的测试:
from timeit import Timer
from fibo import fib t1 = Timer("fib(10)","from fibo import fib") for i in range(1,41):
s = "fibm(" + str(i) + ")"
t1 = Timer(s,"from fibo import fibm")
time1 = t1.timeit(3)
s = "fibi(" + str(i) + ")"
t2 = Timer(s,"from fibo import fibi")
time2 = t2.timeit(3)
print("n=%2d, fib: %8.6f, fibi: %7.6f, percent: %10.2f" % (i, time1, time2, time1/time2))
n= 1, fib: 0.000011, fibi: 0.000015, percent: 0.73
n= 2, fib: 0.000011, fibi: 0.000013, percent: 0.85
n= 3, fib: 0.000012, fibi: 0.000014, percent: 0.86
n= 4, fib: 0.000012, fibi: 0.000015, percent: 0.79
n= 5, fib: 0.000012, fibi: 0.000016, percent: 0.75
n= 6, fib: 0.000011, fibi: 0.000017, percent: 0.65
n= 7, fib: 0.000012, fibi: 0.000017, percent: 0.72
n= 8, fib: 0.000011, fibi: 0.000018, percent: 0.61
n= 9, fib: 0.000011, fibi: 0.000018, percent: 0.61
n=10, fib: 0.000010, fibi: 0.000020, percent: 0.50
n=11, fib: 0.000011, fibi: 0.000020, percent: 0.55
n=12, fib: 0.000004, fibi: 0.000007, percent: 0.59
n=13, fib: 0.000004, fibi: 0.000007, percent: 0.57
n=14, fib: 0.000004, fibi: 0.000008, percent: 0.52
n=15, fib: 0.000004, fibi: 0.000008, percent: 0.50
n=16, fib: 0.000003, fibi: 0.000008, percent: 0.39
n=17, fib: 0.000004, fibi: 0.000009, percent: 0.45
n=18, fib: 0.000004, fibi: 0.000009, percent: 0.45
n=19, fib: 0.000004, fibi: 0.000009, percent: 0.45
n=20, fib: 0.000003, fibi: 0.000010, percent: 0.29
n=21, fib: 0.000004, fibi: 0.000009, percent: 0.45
n=22, fib: 0.000004, fibi: 0.000010, percent: 0.40
n=23, fib: 0.000004, fibi: 0.000010, percent: 0.40
n=24, fib: 0.000004, fibi: 0.000011, percent: 0.35
n=25, fib: 0.000004, fibi: 0.000012, percent: 0.33
n=26, fib: 0.000004, fibi: 0.000011, percent: 0.34
n=27, fib: 0.000004, fibi: 0.000011, percent: 0.35
n=28, fib: 0.000004, fibi: 0.000012, percent: 0.32
n=29, fib: 0.000004, fibi: 0.000012, percent: 0.33
n=30, fib: 0.000004, fibi: 0.000013, percent: 0.31
n=31, fib: 0.000004, fibi: 0.000012, percent: 0.34
n=32, fib: 0.000004, fibi: 0.000012, percent: 0.33
n=33, fib: 0.000004, fibi: 0.000013, percent: 0.30
n=34, fib: 0.000004, fibi: 0.000012, percent: 0.34
n=35, fib: 0.000004, fibi: 0.000013, percent: 0.31
n=36, fib: 0.000004, fibi: 0.000013, percent: 0.31
n=37, fib: 0.000004, fibi: 0.000014, percent: 0.29
n=38, fib: 0.000004, fibi: 0.000014, percent: 0.29
n=39, fib: 0.000004, fibi: 0.000013, percent: 0.31
n=40, fib: 0.000004, fibi: 0.000014, percent: 0.29
python的递归算法学习(2):具体实现:斐波那契和其中的陷阱的更多相关文章
- Python递归及斐波那契数列
递归函数 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数.举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * ... * n,用函数 fact(n)表示,可 ...
- 用递归方法计算斐波那契数列(Recursion Fibonacci Sequence Python)
先科普一下什么叫斐波那契数列,以下内容摘自百度百科: 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因意大利数学家列昂纳多·斐波那契(Leonardoda Fibonacci ...
- {每日一题}:四种方法实现打印feibo斐波那契数列
刚开始学Python的时候,记得经常遇到打印斐波那契数列了,今天玩玩使用四种办法打印出斐波那契数列 方法一:使用普通函数 def feibo(n): """ 打印斐波那契 ...
- python学习笔记之斐波拉契数列学习
著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到: 1, 1, 2, 3, 5, 8, 13, 21, 34, ... 如果用Python的列表生成式, ...
- Python学习之斐波那契数列实现篇
描述 一个斐波那契序列,F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2) (n>=2),根据n的值,计算斐波那契数F(n),其中0≤n≤1000. 输入 输入 ...
- Python学习基础(三)——装饰器,列表生成器,斐波那契数列
装饰器——闭包 # 装饰器 闭包 ''' 如果一个内部函数对外部(非全局)的变量进行了引用,那么内部函数被认为是闭包 闭包 = 函数块 + 定义时的函数环境 ''' def f(): x = 100 ...
- python学习第四十四天斐波那契数列和yield关键词使用
斐波那契数列是数学中的常见的算法,第一个第二个不算,从第三个开始,每个数的都是前面两个数的和,使用yield关键词把生成的数列保存起来,调用的时候再调用,下面举例说明一下 def fab(max): ...
- Python学习笔记_斐波那契数列
""" 1.生成100项斐波那契数列 2.求第n项斐波那契数列的值是多少 3.给定终止值,生成此前斐波那契数列 """ # 求第n项斐波那契 ...
- C语言数据结构----递归的应用(斐波拉契数列、汉诺塔、strlen的递归算法)
本节主要说了递归的设计和算法实现,以及递归的基本例程斐波拉契数列.strlen的递归解法.汉诺塔和全排列递归算法. 一.递归的设计和实现 1.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...
随机推荐
- 十五、mac 中登陆mysql忘记密码解决办法
mac 中登陆mysql忘记密码解决办法 1.打开终端,输入命令:cd /usr/local/mysql/bin 2.mysql -uroot -p,用这条命令登陆时报错信息: 报错:Enter pa ...
- Android stadio 自定义debug release keystore
1.添加siggnig name 随意,不过按我写的就可以了.设置完成之后,你的build.grade就会多出来一些: android { signingConfigs { signingConfig ...
- cycling -avoid the vicious cycle
‘Numerous' studies in the past appear to have shown a link between cycling and ED. The researchers a ...
- VS Extension+NVelocity系列(一)——构建一个简单的NVelocity解析环境
一.前言 本节我们将实际实现一个简单的NVelocity解析环境,以便为以后的实例做一些基本工作,虽然NVelocity如何使用已经属于老掉牙的话题,但我只能专门挑出来一章来做铺垫.人生就是这样无奈啊 ...
- Activiti入门 -- 轻松解读数据库
相关文章: <史上最权威的Activiti框架学习指南> <Activiti入门 --环境搭建和核心API简介> 在Activiti中,相对前身JBPM基础上又额外多了5张,框 ...
- js 请求异常重连或断线后联网重连机制(ajax)
转到到 https://blog.csdn.net/mengtoumingren/article/details/80296788
- appium+python的APP自动化(2)
上节说到安卓上的测试环境都安装好了,这个时候要安装python了 1python的安装 https://www.python.org/15官网下载python2.7(3.0以上也行,个人爱好),安装也 ...
- 孤荷凌寒自学python第四十一天python的线程同步之Event对象
孤荷凌寒自学python第四十一天python的线程同步之Event对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 鉴于Lock锁与RLock锁均宣告没有完全完成同步文件操作的问题,于 ...
- 聊聊、Spring ServletContainerInitializer
我们平时用 Java 注解很多,例如 @Configuration.@Component.@Service,我们习惯于通过 XML 方式来实现 Web,而用 Java 注解方式来实现 Web 却很少. ...
- NYOJ 42 一笔画
一笔画问题 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 zyc从小就比较喜欢玩一些小游戏,其中就包括画一笔画,他想请你帮他写一个程序,判断一个图是否能够用一笔画下 ...