Fibonacci数

斐波那契数列(Fibonacci Sequence)

又称黄金分割数列,或兔子数列(因为是斐波那契观察兔子生殖而总结得到)。

在数学上,被定义为递推式:F(1)=1, F(2)=1, F(3)=2, F(4)=3, F(5)=5, ..., F(n)=F(n-1)+F(n-2)(n≥3)


 单元测试

#include <stdio.h>
#include <time.h>

int R[1000]={0};

int main(void){
    int N = 50;
//    int N = 1e6;
    double start, finish;
    
    start = clock();
    printf("%lld\n", fib(N));
    finish = clock();
    
    printf("%f s", (finish-start)/CLOCKS_PER_SEC);
    
    return 0;
} 

递归实现

根据它的递推表达式,很容易想到使用递归实现。

版本A:

1 int fib_A(int N){
2     if( N <= 2 )
3       return 1;
4     int tmp = fib_A(N-1)+fib_A(N-2);
5     printf("%d: %d\n", N, tmp);
6     return tmp;
7 }

代码很简单,但是计算很慢!算前50个Fibonacci数需要超过60秒。分析算法,发现很多实例在进行重复计算!

如此,根据这一点很容易想到使用查表的形式进行改进。

版本B:

 1 long long fib_B(int N, long long* A){
 2     if( A[N] != 0 )//A已初始化为0
 3       return A[N];
 4       
 5     A[N] = fib_B(N-1, A)+fib_B(N-2, A);
 6     if( R[N] == 0 ){
 7         printf("%d: %lld\n", N, A[N]);
 8         R[N] = 1;
 9     } 
10     return A[N];
11 }

从结果看,仅算前50个改进明显,事实测试中算前10000个数压力都不大(不超过1s)。可以证明得到比较好的改进。


迭代

递归是一种自上而下的算法思路,因此为了计算n,会保留n(压栈)去结算n-1,以此类推,直到碰到递归基,占内存较大(O(n))。而迭代是自下而上,如果能得到迭代表达式,计算应该是非常快且不占空间的(O(1))。

Fibonacci递推式:F(n)=F(n-1)+F(n-2)。可知当前F(n)的结果需要根据前两项得到,因此我们可以使用两个变量,一直保存前两项的值,每次迭代都更新这两项,一直跌到到需要计算的n。

 1 long long fib_itera(int N){
 2     int i; 
 3     long long f, g;
 4     
 5     f = 1; g = 1;//第1项、第2项的值
 6     for( i=3; i<=N; i++){
 7         f = f + g;
 8         g = f - g;
 9         printf("%d: %lld\n", i, f);
10     } 
11     return f;
12 } 

运行速度是跟之前的递归B版本差不多。


Fibonacci数应用

Fibonacci数不仅仅只是在学习递归的时候可以用到,实际中应该是很广泛的。这里举两个例子。

1. Fibonacci查找

是对二分查找的longN的常系数进行改进,可以通过严格的证明,使用Fibonacci黄金分割在查找时对数列进行分割会得到最优的常系数。具体实现与证明与在查找篇给出,这里暂不提。

2. 爬楼梯

也是比较常见的一种面试题:如果每次爬楼梯只能一次跨一个或两个台阶,那么到第n个台阶有多少中走法?语义规定地面算第0个台阶。

第一层台阶:F(1) = 1; 第二层台阶:可以一步一步,也可以一次两步,F(2) = 2;第三层台阶:可以1、1、1,或1、2,或2、1,F(3) = 3;第四层:1、1、1、1,或1、1、2,或1、2、1,或2、1、1,或2、2,F(4) = 5。

得到递推式,F(1) = 1,F(2) = 2,F(n) = F(n-1) + F(n-2)(n>2)。

同理,如果一次可以跨1、2、3个台阶,也一样可以先推理出前几项的值,然后得到递推表达式(变形的Fibonacci数列)。

 

posted @ 2018-09-03 09:44  EasonDongH  阅读(471)  评论(0编辑  收藏  举报