算法之路(三)----查找斐波纳契数列中第 N 个数
算法题目
查找斐波纳契数列中第 N 个数。
所谓的斐波纳契数列是指:
* 前2个数是 0 和 1 。
* 第 i 个数是第 i-1 个数和第i-2 个数的和。斐波纳契数列的前10个数字是:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 …
分析
斐波那契数列满足公式f(n) = f(n-1) + f(n-2),n > 0。这里我们的第一想法是使用递归,可是直接翻译公式出来的递归调用是这样的:
int fib(int n) {
if (n == 1) {
return 0;
}
if (n == 2){
return 1;
}
return fib(n - 1) + fib(n - 2);
}
可是这个函数的事件复杂度恰好是最糟糕的指数级。怎么来证明它是指数级呢?
你可以先用一些测试数来测试一下这个方法:
当n = 40时,大概就需要0.5秒才能计算出来;
当n 为50时,需要等很久才能计算出实际的值。
下面来推导它的时间复杂度。
对于斐波那契数,有定理 :当n >= 0时,Fn < (5/3)n。
首先使用归纳法来证明。对于基准情形,F1 = 0 < 5/3,F2 = 1 < 5/3。
然后假设i = 1,2,3,…,n 成立;这就是归纳假设。那么我们只需要证明出Fn+1 < (5/3)n+1 即可。
根据公式我们可以得出Fn+1 = Fn + Fn-1。
推到过程如下:
Fn+1 < (5/3)n + (5/3)n-1
Fn+1 < (3/5)(5/3)n+1 + (3/5)2(5/3)n+1
Fn+1 < (24/25)(5/3)n+1 < (5/3)n+1
得证 Fn+1 < (5/3)n+1。
同样的证明过程,可以证明出当n > 4时, Fn > (3/2)n。
而T(n) = T(n-1) + T(n-2) + 3。
T(n) >= fib(n) >= (3/2)n。
因此这个函数的运行时间是以指数的速度增长。
可能有点不同的是,有的斐波那契数列是从1,1,2,3,…. 开始,所以有些微的差别。
这只是对级数做了一次平移。我们可以找一些方便证明的情况来证明。
更优解法
其实上面的递归违反了递归的合成效益法则,才导致了运行时间的指数级增长。
递归的四条基本准则:
1、基准情形。必须有总有某些基准情形,它无须递归就能解出。
2、不断推进。对于那些需要递归求解的情形,每一次递归调用都必须要使求解状况朝接近基准情形的方向推进。
3、设计法则。假设所有的递归调用都能运行。
4、合成效益法则。在求解一个问题的同一示例时,切勿在不同的递归调用中做重复性的工作。
我们可以利用一个简单的for 循环来求解第N个斐波那契数。
int fibonacci(int n) {
if (n == 1) {
return 0;
}
if (n == 2) {
return 1;
}
int a = 0;
int b = 1;
int c = 0;
for (int i = 3; i < n + 1; i++) {
c = a + b;
a = b;
b = c;
}
return c;
}
使用两个变量分别保存f(n-1) 和f (n-2),然后从基准情况开始往第 n 个数推进。
改进后的函数时间复杂度是O(n),运行时间大概是 (3n - 1)大大减少了运行时间。
算法之路(三)----查找斐波纳契数列中第 N 个数的更多相关文章
- Java算法求最大最小值,冒泡排序,斐波纳契数列一些经典算法<不断更新中>
清明在家,无聊,把一些经典的算法总结了一下. 一.求最大,最小值 Scanner input=new Scanner(System.in); int[] a={21,31,4,2,766,345,2, ...
- lintcode:Fibonacci 斐波纳契数列
题目: 斐波纳契数列 查找斐波纳契数列中第 N 个数. 所谓的斐波纳契数列是指: 前2个数是 0 和 1 . 第 i 个数是第 i-1 个数和第i-2 个数的和. 斐波纳契数列的前10个数字是: 0, ...
- LintCode 斐波纳契数列
查找斐波纳契数列中第 N 个数. 所谓的斐波纳契数列是指: 前2个数是 0 和 1 . 第 i 个数是第 i-1 个数和第i-2 个数的和. 斐波纳契数列的前10个数字是: 0, 1, 1, 2, 3 ...
- Java算法求最大最小值,倒序,冒泡排序,斐波纳契数列,日历一些经典算法
一,求最大,最小值 int[] a={21,31,4,2,766,345,2,34}; //这里防止数组中有负数,所以初始化的时候给的数组中的第一个数. int max=a[0]; int min=a ...
- java斐波纳契数列
//斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.-- 这个数列从第三项开始,每一项都等于前两项之和. public class DiGui { public ...
- HDU 4639 Hehe(字符串处理,斐波纳契数列,找规律)
题目 //每次for循环的时候总是会忘记最后一段,真是白痴.... //连续的he的个数 种数 //0 1 //1 1 //2 2 //3 3 //4 5 //5 8 //…… …… //斐波纳契数列 ...
- 用PHP迭代器来实现一个斐波纳契数列(转)
斐波纳契数列通常做法是用递归实现,当然还有其它的方法.这里现学现卖,用PHP的迭代器来实现一个斐波纳契数列,几乎没有什么难度,只是把类里的next()方法重写了一次.注释已经写到代码中,也是相当好理解 ...
- 10、end关键字和Fibonacci series: 斐波纳契数列
# Fibonacci series: 斐波纳契数列 # 两个元素的总和确定了下一个数 a, b = 0, 1 #复合赋值表达式,a,b同时赋值0和1 while b < 10: print(b ...
- HDU 5914 Triangle 斐波纳契数列 && 二进制切金条
HDU5914 题目链接 题意:有n根长度从1到n的木棒,问最少拿走多少根,使得剩下的木棒无论怎样都不能构成三角形. 题解:斐波纳契数列,a+b=c恰好不能构成三角形,暴力就好,推一下也可以. #in ...
随机推荐
- TCP/IP学习笔记:TCP传输控制协议(一)
1 TCP的服务 尽管TCP和UDP都使用相同的网络层(IP),TCP却向用户提供一种面向连接的,可靠地字节流服务.两个使用TCP的应用,在彼此交换数据之前必须先建立一个TCP连接,在一个TCP连接中 ...
- BOM,Dom 回顾
加给元素: offsetLeft(距离定位父级的距离)/offsetTop(距离定位父级的距离)/offsetWidth(可视宽度)/offHeight(可视高度) clientLeft(左边框宽度) ...
- Centos常用命令之:ln
在linux中[ln]这个命令用来创建连接文件. 共有两种连接文件:一种是类似与Windows的快捷方式(软链接),另一种就是通过文件系统的inode来产生的新的文件名(硬链接). 这里解释下什么叫i ...
- [NOI 2010]航空管制
Description 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此,小X表示很不满意. 在这次来烟台的路上 ...
- [HAOI2015]数字串拆分
题目描述 你有一个长度为n的数字串.定义f(S)为将S拆分成若干个1~m的数的和的方案数,比如m=2时,f(4)=5,分别为4=1+1+1+1你可以将这个数字串分割成若干个数字(允许前导0),将他们加 ...
- ●BZOJ 3270 博物馆
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3270题解: 期望DP,高斯消元 本来是定义的关于概率的dp, 但是发现这样定义有很多解释不通 ...
- 【Codeforces Round 438 A B C D 四个题】
题目所在比赛的地址在这里呀 A. Bark to Unlock ·述大意: 输入一个目标串.然后输入n(1<=n<=100)个串,询问是否可以通过这些串收尾相接或者它本身拼出目 ...
- hdu 1133 Buy the Ticket(Catalan)
Buy the Ticket Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) T ...
- python MySQLdb pymsql
参考文档 https://www.python.org/dev/peps/pep-0249/#nextset 本节内容 MySQLdb pymysql MySQLdb和pymysql分别为Pytho ...
- matplotlib中subplot的各参数的作用
subplot(a,b,c)中a代表所画图形的行数 b代表所画图形的列数 c代表所画图形的序号. plt.figure(facecolor='w', figsize=(9, 10)) plt.subp ...