斐波那契数列的优化

科普一下:

Fibonacci)斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*

现在输入n(n > 1),求第n位斐波那契数

代码1:简单实现

public static long computeRecursively(int n){

if(n > 1)

return computeRecursively(n-2)+computeRecursively(n-1);

else

return n;

}

分析:计算n=30时,斐波那契数用了2692537次调用,这里的大数量的递归将会是我们关注的效率瓶颈。我们发现,每个斐波数(少于2除外),都需要开启两个递归方法来实现

因此,我们可以优化为一个递归来实现。如下:

代码2:优化递归

public static long computeRecursivelyWithLoop(int n){

if(n > 1){

long result = 1;

do{

result += computeRecursivelyWithLoop(n-2);

n--;

}while(n > 1);

return result;

}else

return n;

}

分析,这里的递归,计算n=30时,产生的递归调用有1346269次,对比上面的计算方法,效率快了一倍,但是依然是低效率的方法。接下来,我们考虑下非递归(迭代法)

代码3:public static long computeIteratively(int n){

if(n > 1){

long a = 0, b =1;

do{

long tmp = b;

b += a;

a = tmp;

n--;

}while( n > 1);

return b;

}

return n;

}

分析:这里的思路主要是从斐波数的性质出发。可以看出代码有交换的意图,易知b比a大。由于第n项由等于前两项的和,所以,每次计算F(N) = F(N-1)+F(N-2) <=> b = b + a;所以每次只需将b 覆盖 a ,b+a覆盖b, 就可以向后继续计算。因为其是线性的,效率大大提高。计算computeIteratively的次数少于10万次。

最快一些?可以。考虑下,如果n是奇数,则a = 0,b = 1。n是偶数的话,则a = 1 ,b = 1。

代码4:

public static long computeIterattivelyFaster(int n){

if(n > 1){

long a , b  = 1;

n--;

a = n & 1;

n /= 2;

while( n > 0){

n --;

a += b;

b += a;

}

return b;

}

return n;

}

这里新版本主要在于每次只迭n /= 2; 每次循环直接计算两个斐波数,所以速度又快了一倍。但是会有个缺陷,JAVA的long是64位,意味着在计算n > 92时会溢出,大家注意一下。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值