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.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...
随机推荐
- 15.6,redis主从同步
redis主从同步 原理:1. 从服务器向主服务器发送 SYNC 命令.2. 接到 SYNC 命令的主服务器会调用BGSAVE 命令,创建一个 RDB 文件,并使用缓冲区记录接下来执行的所有写命令.3 ...
- Kafka安装和常用操作命令
Kafka安装: 下载kafka_2.10-0.8.2.1 1.关闭防火墙 2.修改配置文件 server.properties broker.id=1log.dirs= /usr/kafka_2. ...
- 获取IMSI
转:http://letsunlockiphone.guru/find-imsi-number/ HOW TO FIND IMSI NUMBER (UPDATED) You probably alre ...
- Eclipse 工作空间(Workspace)---Eclipse教程第07课
Eclipse 工作空间(Workspace) eclipse 工作空间包含以下资源: 项目 文件 文件夹 项目启动时一般可以设置工作空间,你可以将其设置为默认工作空间,下次启动后无需再配置: 工作空 ...
- iOS程序执行顺序和UIViewController 的生命周期(整理)
说明:此文是自己的总结笔记,主要参考: iOS程序的启动执行顺序 AppDelegate 及 UIViewController 的生命周期 UIView的生命周期 言叶之庭.jpeg 一. iOS程序 ...
- CMake Tutorial & Example
Tutorial CMakeLists用于告诉CMake我们要对这个目录下的文件做什么事情 cmake 的特点主要有: 1,开放源代码,使用类 BSD 许可发布.http://cmake.org/HT ...
- python pip install XXX出现报错问题
重装Anacondas后,将pip 和python.exe路径加入到环境变量后直接在cmd窗口进行pip 操作,报错如下 报错内容为: pip is configured with locations ...
- 201621123034 《Java程序设计》第13周学习总结
作业13-网络 1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以 ...
- error MSB6006: “aapt.exe”已退出,代码为-1073741819
今天升级了Xamarin和Android SDK之后连模板程序生成都报这个错误,真是想剁手啊,最后在google同学的帮助下搜索到了Xamarin官方论坛上的回答 这个问题是生成工具版本选择的问题,似 ...
- 四、vue派发更新
收集的目的就是为了当我们修改数据的时候,可以对相关的依赖派发更新,那么这一节我们来详细分析这个过程. setter 部分的逻辑: /** * Define a reactive property on ...