花式破解斐波那契数列
斐波那契数列想必大家都听过,如果感觉斐波那契数列有点陌生的同学,肯定是没有好好学算法。一般在讲解递归的时候,我们都会拿出斐波那契数列这个例子来,因为它实在太经典了,今天我们就来深入研究一下斐波那契数列的解法。
什么是斐波那契数列?
数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。他当时是这样提出的:假设一对刚出生的小兔一个月后就能长成大兔,再过一个月就能生下一对小兔,并且此后每个月都生一对小兔,一年内没有发生死亡,问:一对刚出生的兔子,一年内繁殖成多少对兔子?
形成数列就是:0、1、1、2、3、5、8、13、21、34、……
在数学上,斐波那契数列以如下被以递推的方法定义:F( 0 )=0,F( 1 )=1, F( n )=F( n - 1 ) + F( n - 2 )(n≥ 2,n ∈ N*)
解法一:递归
时间复杂度:O(2ⁿ)
空间复杂度:O(1)
斐波那契数列就是为递归而生的,我们从题中就可以找到它的规律就是后一个数是前两个数之和,它的边界就是F( 0 )=0,F( 1 )=1,它的递归调用就是 F( n - 1 ) + F( n - 2 ) 。
原理图:
代码如下:
public int fibonacci(int n) {if (n < 2) {return n;}return fibonacci(n-1) + fibonacci(n-2);
}
复制代码
解法二:记忆化搜索(备忘录算法)
时间复杂度:O(n)
空间复杂度:O(n)
通过上边递归的原理图片可以看出,递归时大量的中间数据是存在重复计算的,我们将这些重复的中间值通过Map缓存起来,这样同样的值我们只需要递归计算一次,就能得到解,能够极大的提高递归的效率,这就是记忆化搜索。
此种算法,是典型的用空间换时间,有n个数我们就需要缓存n个值。
优化后我们需要的计算量,是不是大幅提升呢,从下图就可以得到答案
代码如下:
public int fibonacci(int n, Map<Integer,Integer> cache) {if (n < 2) {return n;}if (cache.containsKey(n)) {return cache.get(n);}int value = fibonacci(n - 1, cache) + fibonacci(n - 2, cache);cache.put(n,value);return value;
}
复制代码
解法三:动态规划
时间复杂度:O(n)
空间复杂度:O(1)
递归是一种自顶向下求解的过程,那么我们能不能自低向上求解呢?
自低向上就是说我们由F( 0 )=0,F( 1 )=1,F( 2 )...F( n )这样是不是更好呢?很显然可以的。
正是由于斐波那契数存在这种递推关系,所以我们可以使用动态规划求解。动态规划的状态转移方程即为上述递推关系,边界条件为 F(0) 和 F(1)。
根据动态规划的状态转移方程和边界条件,我们可以得到时间复杂度和空间复杂度都是 O(n) 的实现。由于 F(n) 只和 F(n−1) 与 F(n−2) 有关,因此可以使用 【滚动数组思想】 把空间复杂度优化成 O(1)。
代码如下:
public int fibonacci(int n) {if (n < 2) {return n;}int p = 0, q = 0, r = 1;for (int i = 2; i <= n; ++i) {p = q; q = r; r = p + q;}return r;}
}
复制代码
解法四:矩阵快速幂
时间复杂度:O(logn)
空间复杂度:O(1)
动态规划的时间复杂度是 O(n)。我们可以使用矩阵快速幂的方法来降低时间复杂度。
首先构建递推关系:
得到
令
public int fibonacci(int n) {if (n < 2) {return n;}int[][] q = {{1, 1}, {1, 0}};int[][] res = pow(q, n - 1);return res[0][0];
}
public int[][] pow(int[][] a, int n) {int[][] ret = {{1, 0}, {0, 1}};while (n > 0) {if ((n & 1) == 1) {ret = multiply(ret, a);}n >>= 1;a = multiply(a, a);}return ret;
}
public int[][] multiply(int[][] a, int[][] b) {int[][] c = new int[2][2];for (int i = 0; i < 2; i++) {for (int j = 0; j < 2; j++) {c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];}}return c;
}
复制代码
解法五:通项公式
斐波那契数 F(n) 是齐次线性递推,根据递推方程 F(n)=F(n-1)+F(n-2),
可以写出这样的特征方程:x²=x+1
代码中pow 函数的时间、空间复杂度与 CPU 支持的指令集相关,这里不深入分析。
代码如下:
public int fibonacci(int n) {double sqrt5 = Math.sqrt(5);double fibN = Math.pow((1 + sqrt5) / 2, n) - Math.pow((1 - sqrt5) / 2, n);return (int) Math.round(fibN / sqrt5);
}
复制代码
说明:
解法四,解法五是在LeetCode题解中上发现的,效率是真的高,但我看的也是模棱两可,这些都是高等数学的相关知识点,感兴趣的可以深入研究一下,算法的尽头还是数学啊!!!
前三个解法是我们每个人都应该掌握的。
花式破解斐波那契数列相关推荐
- 采用数组实现斐波那契数列的计算、foreach循环的使用、100以内质数的判断
想要实现斐波那契数列的计算,我们首先得了解斐波那契数列的定义及其原理: 斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契以兔子繁殖为例子而引入,故又称 ...
- 兔子繁衍问题-暴力破解+斐波那契
解法1.我是用暴力破解,循环解决 #include<iostream> using namespace std; /*一对兔子,从出生后第3个月起每个月都生一对兔子. 小兔子长到第3个月后 ...
- java 斐波拉_Java实现斐波那契数列
斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.--在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n&g ...
- 剑指offer:面试题10- I. 斐波那契数列
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项.斐波那契数列的定义如下: F(0) = 0, F(1) = 1 F(N) = F(N - 1) + F(N - 2), 其中 ...
- 用递归法计算斐波那契数列的第n项
斐波纳契数列(Fibonacci Sequence)又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.--在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1, ...
- 循环斐波那契数列_剑指offer #10 斐波那契数列
(递归和循环)#10 斐波那契数列 一.斐波那契数列 定义: n = 0 , f(n) = 0 n = 1 , f(n) = 1 n > 1 , f(n) = f(n-1) + f(n-2) 思 ...
- 用C语言编写:判断一个≥2的整型数是否存在于斐波那契数列中?
自己写的,感觉挺有成就感的,就展示出来吧! 判断一个≥2的整型数是否存在于斐波那契数列中? 若存在,则返回第几项:若不在,则返回-1 #include <stdio.h> long gen ...
- 算法(1)斐波那契数列
1.0 问题描述 实现斐波那契数列,求第N项的值 2.0 问题分析 斐波那契数列最简单的方法是使用递归,递归和查表法同时使用,可以降低复杂度. 根据数列特点,同时进行计算的数值其实只有3个,所以可以使 ...
- NOIP模拟题 斐波那契数列
题目大意 给定长度为$n$序列$A$,将它划分成尽可能少的若干部分,使得任意部分内两两之和均不为斐波那契数列中的某一项. 题解 不难发现$2\times 10^9$之内的斐波那契数不超过$50$个 先 ...
最新文章
- 使用Docsify搭建Markdown文件服务器
- 扑克牌图片一张一张_Python 制作一副扑克牌,有趣的案例
- python控制手机自动刷新闻_python +adb控制手机自动化签到
- 日期/时间格式/解析,Java 8样式
- Pytorch LSTM初识(详解LSTM+torch.nn.LSTM()实现)1
- Matlab语音采集与读写程序,基于MATLAB的语音信号录制采集和分析的程序设计
- mycat两个mysql实例的搭建_Mycat-多实例的搭建
- python数值运算操作符也叫做内置操作符_Python的操作符 - osc_r1gtal48的个人空间 - OSCHINA - 中文开源技术交流社区...
- (洛谷)P2709 小B的询问
- 从医生看病和快餐店点餐理解Node.js的事件驱动
- android禁止锁屏保持常亮
- Atitit 微服务实践 艾提拉著 微服务主要解决几个问题负载均很 目录 1. 微服务的模式 http请求层 vs服务层	1 1.1. Http vs 服务层优缺点	1 2. 实现技术	2
- (转)美国国家科学院院士张首晟演讲全文:人工智能的三大发展支柱
- Bing API 将新增 Bing 空间数据服务
- web前端开发师前景,96道前端面试题
- 如何把视频转换成mp3格式
- 天蓝色在ps中的色值_天蓝色事件网格集成测试
- NGUI学习笔记(四).Sprite的Sliced类型与解决拉伸模糊的问题
- 美团机器学习InAction系列—实例详解机器学习如何解决问题
- PageAdmin CMS仿站教程,自己建网站就是如此简单