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.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...
随机推荐
- easyui js拼接html,class属性失效的问题
问题:要在前一个按钮之后添加相同的样式的按钮,通过$("#cj").html(str); 这样的形式添加,却不能添加上样式 <div id="btn" c ...
- laravel5.5路由使用name的好处
使用name的好处 辅助函数 route 可以用于为指定路由生成 URL.命名路由生成的 URL 不与路由上定义的 URL 相耦合.因此,就算路由的 URL 有任何更改,都不需要对 route 函数调 ...
- 【APUE】Chapter11 Threads
看完了APUE第三版的Chapter11 Threads,跟着书上的demo走了一遍,并且参考了这个blog(http://www.cnblogs.com/chuyuhuashi/p/4447817. ...
- CMDB项目实战
01-CMDB项目介绍 02-CMDB开发背景 03-CMDB开发目的 04-CMDB资产采集方式之agent 05-CMDB资产采集方式之ssh 06-CMDB资产采集方式之saltstack 07 ...
- 孤荷凌寒自学python第四十三天python 的线程同步之Queue对象
孤荷凌寒自学python第四十三天python的线程同步之Queue对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) Queue对象是直接操作队列池的对象,队列中可以存放多种对象,当然也 ...
- Bat 修改 xml 文件标签值
xml 文件如下: <ConfigurationData> <ReportsFolder>\Reports</ReportsFolder> <Helpfold ...
- eclipse 运行错误:在类XXX中找不到 main 方法, 请将 main 方法定义为: public static void main(String[] args) 否则 JavaFX 应用程序类必须扩展javafx.application.Application
新建了一个类Hello: 代码: 第一次运行报错: 点击关闭该类的界面时出现: 点击是,然后再次打开,可以正确执行,结果为: 这是为什么....,后来发现了原因:是每次运行或调试前没有自动保存编辑的内 ...
- Alpha 冲刺(5/10)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成了主界面的基本布局 ...
- 软工实践Alpha冲刺(6/10)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成了主界面的基本布局 ...
- ocrosoft Contest1316 - 信奥编程之路~~~~~第三关 问题 C: 挂盐水
http://acm.ocrosoft.com/problem.php?cid=1316&pid=2 题目描述 挂盐水的时候,如果滴起来有规律,先是滴一滴,停一下:然后滴二滴,停一下:再滴三滴 ...