目录

1.斐波那契数简介

2.计算斐波那契数

3.时间复杂度计算

4.空间复杂度计算

5.斐波那契非递归实现

6.怎么在时间复杂度O(1),空间复杂度O(1)下计算斐波那契数


1.斐波那契数简介

斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从 1963 年起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。

这个问题并不是很复杂,但是从这个问题本身来分析时间复杂度和空间复杂度问题。

2.计算斐波那契数

序列依次为1,1,2,3,5,8,13,21,...问题:怎么求出序列中第N个数字?递归需要注意退出条件,避免死循环。

如果使用递归的话,当输入比较大数字40或者更大的数字的时候,就会计算非常慢,甚至计算不出结果。这个时候我们就要计算算法的时间复杂度和空间复杂度,首先我们看一下时间复杂度。

3.时间复杂度计算

我们通过上面那个程序,我们通常通过递归树的方式计算这个递归的时间复杂度。求解F(n),必须先计算F(n-1)和F(n-2),计算F(n-1)和F(n-2),又必须先计算F(n-3)和F(n-4)。。。。。。以此类推,直至必须先计算F(1)和F(0),然后逆推得到F(n-1)和F(n-2)的结果,从而得到F(n)要计算很多重复的值,在时间上造成了很大的浪费,算法的时间复杂度随着N的增大呈现指数增长,时间的复杂度为O(2^n),即2的n次方。

网上还有另一个版本的求时间复杂度方法,也附在下面了:

4.空间复杂度计算

类似于时间复杂度的讨论,一个算法的空间复杂度S(n)定义为该算法所耗费的存储空间(存储变量的空间),它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。空间复杂度(SpaceComplexity)是对一个算法在运行过程中临时占用存储空间大小的量度。一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。算法的输入输出数据所占用的存储空间是由要解决的问题决定的,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。存储算法本身所占用的存储空间与算法书写的长短成正比,要压缩这方面的存储空间,就必须编写出较短的算法。算法在运行过程中临时占用的存储空间随算法的不同而异,有的算法只需要占用少量的临时工作单元,而且不随问题规模的大小而改变,我们称这种算法是“就地\”进行的,是节省存储的算法,有的算法需要占用的临时工作单元数与解决问题的规模n有关,它随着n的增大而增大,当n较大时,将占用较多的存储单元,例如快速排序和归并排序算法就属于这种情况。

一个递归,我们应该怎么计算他的空间复杂度呢?这样的代码效率十分低下,每次递归相当于是重新在原有的函数栈帧上再次开辟空间来运行函数,直到函数找到了递归出口。可见当n = 5的时候,函数一共被调用了九次,这个就是问题所在,f(5)被调用了好多次,实际上调用一次就行,只要函数未到达递归出口(n < = 2)就会一直在现有函数栈上开辟新的空间,所以也很好地说明了为什么函数递归太深会引起栈溢出的现象。每次上下文切换,都有内存空间的使用(内存占用可以是变量占用,也可以是上下文空间切换【用stack实现】)。

下面的过程,就是展现上下文空间切换时候,stack中不断入栈出栈过程

程序结束之后,main也会出栈,我们可以看到在运行f(8)的时候,我们最多用到的资源是8个内存空间。空间复杂度就是树的高度 O(n)。

5.斐波那契非递归实现

我们可以维护一个数组,但是可能会有一些额外开销,因为结果只与前面两个数字相关,存储一个数字必定还是比存储两个数字占用内存大一些。

从n(>2)开始计算,用F(n-1)和F(n-2)两个数相加求出结果,这样就避免了大量的重复计算,它的效率比递归算法快得多,算法的时间复杂度与n成正比,即算法的时间复杂度为O(N)。上面程序空间复杂度O(N),下面空间复杂度O(1)。

6.怎么在时间复杂度O(1),空间复杂度O(1)下计算斐波那契数

斐波拉契数列的计算是一个非常经典的问题,对于小规模的n,很容易用递归的方式来获取,对于稍微大一点的n,为了避免递归调用的开销,可以用动态规划的思想轻松获得,时间复杂度为O(n),空间复杂度为O(1). 但是对于更大规模,比如上题中的n的范围,动态规划所花的时间也不少了。

考虑下面三个矩阵:

F(n)   F(n-1)        1,1         F(n-1)  F(n-2)

F(n-1) F(n-1)  与   1,0   与   F(n-2)  F(n-3)

分别设为S(n), M, S(n-1).  S(n) = M x S(n-1).

于是

S(n) = M^(n-1) x S(1) = M^n;   (关系1)

再来看看,若n为32位正整数,设c[32]为其二进制序列的逆序列, c[i] =0,1;

n = Σ(c[i]*2^i),  i=0,...,31;

所以只要我知道M的2^i 方幂(i=0,1,2,...,31),我们可以轻松计算出S(n)

而计算出32个M的幂需要做32次矩阵乘法,而计算M^n次方,即M^( Σ(c[i]*2^i) ) 也最多需要做32次矩阵乘法

因而最多64次矩阵乘法即可计算出任意32位正整数范围的n对应的S(n)

通过斐波那契数列探讨时间复杂度和空间复杂度相关推荐

  1. 【数据结构】递归斐波那契数列的时间复杂度、空间复杂度

    递归斐波那契数列的时间复杂度相对于循环等函数而言并不容易看出来,下面通过斐波那契数列的程序进行图解: long long Fib(size_t N) {if (N < 3)return 1;re ...

  2. 斐波那契递归调用次数_递归求解斐波那契数列的时间复杂度——几种简洁证明...

    TL:DR: 暴力递归求解斐波那契数列的时间复杂度的紧界不是 ,而是 . 本文将给出几个简洁证明 用最暴力的方法求解斐波那契数列,时间复杂度是多少?具体地说,就是求下面这个程序的复杂度: def fi ...

  3. 斐波那契数列的时间复杂度

    int f(int n) {if (n == 1) return 1;if (n == 2) return 2;return f(n-1) + f(n-2); } 这样一段代码的时间复杂度是多少呢?你 ...

  4. 时间复杂度 ( 递归实现阶乘、斐波那契数列第n个数) / 空间复杂度

    1 时间复杂度   时间复杂度是衡量程序运行的快慢,对于一个程序来说,运行速度的快慢,有很多干扰因素,不同的硬件条件都可能影响到速度的快慢.时间复杂度来衡量,不是精确的衡量,只是单纯从代码本身衡量程序 ...

  5. 斐波那契数的时间复杂度、空间复杂度详解

     斐波那契数:斐波那契数列指的是1.1.2.3.5.8.13.21.······这样一个数列,我们可以发现它后面的一个数是前两个数之和.而在这个数列中的数就被称为斐波那契数. 时间复杂度:时间复杂 ...

  6. 7种方式实现斐波那契数列

    7种方式实现斐波那契数列 一:递归实现   在学校里学习递归的时候,老师就喜欢举斐波那契这个例子,看!多简洁清晰.其实这个例子是非常不适合作为递归举例的,   原因就是效率太慢,除了最后一个数,每个数 ...

  7. 用php递归求fibonacci数列,C++_C语言求Fibonacci斐波那契数列通项问题的解法总结,一:递归实现使用 - phpStudy...

    C语言求Fibonacci斐波那契数列通项问题的解法总结 一:递归实现  使用公式f[n]=f[n-1]+f[n-2],依次递归计算,递归结束条件是f[1]=1,f[2]=1. 二:数组实现  空间复 ...

  8. fibonacci数列前20项_面试题精选:神奇的斐波那契数列

    斐波那契数列,其最开始的几项是0.1.1.2.3.5.8.13.21.34-- ,后面的每一项是前两项之和,事实上,斐波那契在数学上有自己的严格递归定义. f0 = 0 f1 = 1 f(n) = f ...

  9. 算法之矩阵计算斐波那契数列

    算法之矩阵计算斐波那契数列 本节内容 斐波那契介绍 普通方式求解斐波那契 矩阵概念 矩阵求幂 矩阵求解斐波那契 1.斐波那契介绍 斐波那契数列有关十分明显的特点,那是:前面相邻两项之和,构成了后一项. ...

  10. python用递归法写斐波那契_python实现斐波那契数列: 递归+备忘录法+动态规划实现...

    1.为什么备忘录法和动态规划法: 斐波那契是很多人入门递归思想的第一课,所以很多人都会最简单的一种递归写法,但是其实递归的过程,他的时间复杂度非常高,达到了O(2的n次方)这样的一个指数级别. 先看最 ...

最新文章

  1. 计算机启动和操作系统加载小话
  2. mysql配置_Mysql配置 max_allowed_packet
  3. bash shell实现二进制与十进制数的互转
  4. 联想昭阳k29轴拆机步骤图_UG8.5编程加工之固定轴曲面轮廓铣削加工方法
  5. ssm 返回json配置_摆脱困境:将运行时配置作为JSON返回
  6. HTML5 css链接添加不同的样式
  7. 输变电设备物联网传感器数据通信规约_输变电设备“智慧物联”提升电网质效...
  8. Lock(ReentrantLock)实现线程同步,线程安全
  9. java判断题及答案_Java面试题及解析(判断题)
  10. matlab 实现行程编码 对二值图像进行编解码
  11. webService发布和调用--Axis2
  12. CentOS 6.5 中安装Jenkins
  13. 电子书城系统设计与实现
  14. 核磁共振成像基本原理——杨正汉(1)
  15. python画代码流程图_python如何画流程图
  16. 希尔伯特空间巴拿赫空间空间上的翻译
  17. 个人博客和微信公众号
  18. Android-简单单词书app
  19. windows的由来与详细介绍
  20. BZOJ1057: [ZJOI2007]棋盘制作

热门文章

  1. 流程图基础绘制方法和流程图制作软件功能详解
  2. R平方值python实现
  3. 图像识别最好的算法,图片相似度识别算法
  4. linux media v4l2,Overview of the V4L2 driver framework (v4l2_subdev)
  5. 数学建模:多项式拟合并判断可决系数R²
  6. mysql mtq_mysql实现远程登录
  7. Conventional Commits那些事
  8. EXCEL 编辑公式时如何固定某一个单元格
  9. 3D迷宫(DirextX9)
  10. 吴恩达课程作业中的lr_utils下载