Algorithm Gossip: 费式数列
2018-03-18 21:31
323 查看
From Gossip@caterpillar
Algorithm Gossip: 费式数列
说明
Fibonacci为1200年代的欧洲数学家,在他的著作中曾经提到:“若有一只免子每个月生一只小免子,一个月后小免子也开始生产。起初只有一只免 子,一个月后就有两只免子,二个月后有三只免子,三个月后有五只免子(小免子投入生产)......”。如果不太理解这个例子的话,举个图就知道了,注意新生的小免子需一个月成长期才会投入生产,类似的道理也可以用于植物的生长,这就是Fibonacci数 列,一般习惯称之为费氏数列,例如以下:
1、1 、2、3、5、8、13、21、34、55、89......
解法
依说明,我们可以将费氏数列定义为以下:fn = fn-1 + fn-2 if n > 1
fn = n if n = 0, 1
演算法
费氏阵列的解法很多,基本上可以使用递回解,演算法最简单,如下:Procedure FIB(N) [ IF (N < 0) PRINT ("输入错误"); IF (N = 0 OR N = 1) RETURN (N); ELSE RETURN ( FIB(N-1) + FIB(N-2) ); ]
简单,但是不实用,因为太慢了,在求每一个费氏数时,都会发生严重的重覆计算,也就是递回该行 ( FIB(N-1) + FIB(N-2) ),最差的big-o可以到2的n/2次方,画张递回的树状图就可以知道重覆计算的数有多少了。
可以采取非递回的版本,可以将big(o)减至n,演算法如下:
Procedure FIB(N) a = 1; b = 1; FOR i = 2 TO N [ temp = b; b = a + b; a = temp; ] RETURN b; ]
若想要一次列出所有N之前的费氏数,则可以将for回圈的部份改以阵列,也就是:
F(0) = 0; F(1) = 1; FOR i<-2 TO N [ F(i) = F(i-1) + F(i-2); ]
费氏阵列并不是使用递回来解一定不好,事实上单就执行次数上来说,有一个使用递回的演算法可以更快 (big(o)是以2为底的Logn值),但是要使用到乘法运算,所以实际上要看所使用的机器而定。
Procedure FIB(N) IF (n <= 1) RETURN(n); IF (n = 2) RETURN(1); ELSE [ i = n/2; f1 = FIB(i+1); f2 = FIB(i); IF (n mod 2 = 0) RETURN( f2*(2*f1-f2) ); ELSE RETURN ( f1**2+f2**2 ); ] ]
您可以实际使用费氏数列来印证演算法中的那两条公式,其中f1**2表示f1的平方;若将递回的树状图画出来,就像这样:
另外费氏数列还有公式解,导证方式就不提了:
您说,如果免子不只生一只小免子的话怎么办?像这种问题,我们可以将费氏数列加以扩充,称之为扩充费氏数列:
fn = X * fn-1 + Y * fn-2 if n > 1
fn = 1 if n = 0, 1
当X、Y等于1时,自然就是一般的费氏数列了。
想了解费氏数列与自然界神奇的关系,可以造访这个 网页。
实作
C#include <stdio.h> #include <stdlib.h> #define N 20 int main(void) { int Fib = {0}; int i; Fib[0] = 0; Fib[1] = 1; for(i = 2; i < N; i++) Fib[i] = Fib[i-1] + Fib[i-2]; for(i = 0; i < N; i++) printf("%d ", Fib[i]); printf("\n"); return 0; }
Java
public class Fibonacci { public static void main(String[] args) { int[] fib = new int[20]; fib[0] = 0; fib[1] = 1; for(int i = 2; i < fib.length; i++) fib[i] = fib[i-1] + fib[i-2]; for(int i = 0; i < fib.length; i++) System.out.print(fib[i] + " "); System.out.println(); } }
相关文章推荐
- Objective-C实现Algorithm Gossip: 费式数列代码
- C#算法大全-2-Algorithm Gossip: 费式数列
- [置顶] Algorithm : 费式数列
- Algorithm-Gossip(2) 费布拉切数列
- Fibonacci 费式数列
- Algorithm Gossip(14) 蒙地卡罗法求 PI
- Algorithm Gossip (22) 中序式转后序式(前序式)
- 简单算法之费式数列
- 费式数列
- Algorithm Gossip (16) 超长整数运算(大数运算)
- Algorithm Gossip (24) 洗扑克牌(乱数排列)
- 2,费式数列
- Algorithm Gossip: 河内塔
- 费式数列的几种解法
- Algorithm-Gossip 经典算法系列 说明文档
- Algorithm Gossip (17) 长 PI
- Algorithm Gossip: 筛选求质数
- 费式数列
- Algorithm-Gossip(1) 河内之塔 / 汉罗塔
- AlgorithmGossip (19) 完美数