斐波那契数列的定义:

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家列安纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、.....在数学上,斐波那契数列以如下递归的方法定义:F(1)=1,F(2)=1,F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)

翻译成Java代码是:

  public int Fibonacci(int n) {
if (n == 1 || n == 2) {
return 1;
}
return Fibonacci(n - 1) + Fibonacci(n - 2);
}

代码很简单,简单的递归。

但是这个方法在实际执行的过程中可能出现java.lang.StackOverflow错误,这个错误是什么意思呢?jdk官方文档的解释:应用程序递归太深二发生堆栈溢出时,抛出该错误。

Java程序运行时,会在内存中划分5片空间进行数据的存储。分别是:1、寄存器;2、本地方法区;3、方法区;4、栈;5、堆。我们上面说的堆栈指的就是栈,java栈中主要存储基本数据类型的值和对象的引用。那么在上面这个递归执行的过程中发生了什么呢?

我们先分析一下这个数列的公式:

F(n)=F(n-1)+F(n+-2)

  =(F(n-2)+F(n-3))+(F(n-3)+F(n-4))

  =F(n-3)+F(n-4)+F(n-4)+F(n-5)+F(n-4)+F(n-5)+F(n-5)+F(n-6)

  ......

观察可以发现,这个方法在执行的过程中每多增加一层递归需要存储临时参数的栈空间就是上一层的两倍,而在最终结束前,每一层的方法参数n的值都不会被释放(出栈),所以栈的深度将会以O(2^n)的空间复杂度越压越深,最终达到醉倒深度导致栈溢出。

毫无疑问,对实现一个斐波那契数列来说,这个实现空间复杂度O(2^n)太大了,而实际上每一层方法传入的参数值n在成功传到下一层的时候就没用了,但是却一直不能出栈,导致了栈空间的浪费。

所以要优化这个算法,我们就只能让每层方法借宿后及时出栈,也就是别用递归。不用递归用什么呢?

很多时候,递归的功能可以通过循环来实现,循环内部的代码看恶意看做是一个方法的方法体,与递归不同的地方是循环代码没有返回值,但我们可以通过循环内部更改外部变量的值来实现类似于返回值的效果。有公式F(n)=F(n-1)+F(n-2),且已知F(1)=1和F(2)=1,F(3)=1+1=2,F(4)=F(3)+F(2)=2+1=3,利用这个思路,我们可以得到如下代码:

  public int Fibonacci(int n) {
int l = 1, j = 1, k = 1;
for (int i = 3; i <= n; i++) {
k = l + j;
l = j;
j = k;
}
return n == 0 ? 0 : k;
}

解释一下: l 和 j 一开始分别为F(1)和F(2)的值,k为返回的值,循环从n>2时开始(小于等于2直接返回k的初始值),没循环一层,k的值变为前两项 l 和 j 的和,然后更新 l 和 j 的值供下次循环使用。

改良后的算法最大的特点就是栈深度只有一层,没有无用的变量值浪费空间,空间复杂度达到了最优。


原文链接:https://www.cnblogs.com/JackPn/p/9383450.html

最新文章

  1. Azure ARM (14) 设置ARM VM的Availability Set
  2. SharePoint Fundation 2013中SecurityTokenServiceApplication错误
  3. redis + spring 集成
  4. python logging模块详解[转]
  5. Could not find action or result
  6. eclipse git插件配置
  7. Windows编程中的堆管理(过于底层,一般不用关心)
  8. sql如果存在就修改不存在就新增
  9. get set
  10. lxml 解析字符处理规则
  11. selenium +python webdriver运行时报错cannot find Chrome binary
  12. Java中Comparable和Comparator区别
  13. ASP.NET C# 如何在程序中控制IIS服务或应用程序池重启?
  14. 潭州课堂25班:Ph201805201 爬虫基础 第八课 selenium (课堂笔记)
  15. antd-mobile使用报错
  16. tensorflow 指定使用gpu处理,tensorflow占用多个GPU但只有一个在跑
  17. Java-分治算法
  18. [ERR] Not all 16384 slots are covered by nodes.
  19. 深入理解MongoDB的复合索引
  20. 【熊猫TV】《程序员》:聚光灯下的熊猫TV技术架构演进

热门文章

  1. CSS3动画相关属性详解
  2. 深入解析d3弦图
  3. iptable规则的执行顺序
  4. XLSX.js 导出Excel demo
  5. 二、windows下搭建vue开发环境+IIS部署
  6. docker容器内存和CPU使用限制
  7. ParallelForTransform作业
  8. 2019/5/13 洛谷P4742 【tarjan缩点 + 拓扑dp】
  9. Find Duplicate File in System
  10. 【转帖】NAT类型及转换原理深入剖析