实现裴波纳契数列_算法(三)-- 斐波那契数列的三种实现

斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)。

本文介绍斐波那契数列的三种实现,时间复杂度分别为O(2**N),O(N), O(logN)

递归实现

public static int getFib(int n){ if (n < 1) { return 0; } else if(n == 1 || n ==2){ return 1; }else{ return getFib(n - 1) + getFib(n - 2); } }

递归存在的问题就是会重复计算很多值,以5为例,这里的3、2、1都会计算多次,浪费很多资源,我们可以把前面的结果存起来,这样就不需要重复计算前面的值了,也就是O(N)的实现。

4548f6005143171bec46fdec4f13ce4d.png

O(N)的实现

public static int getFib(int n){

if (n < 1) {

return 0;

} else if(n == 1 || n ==2){

return 1;

}else{

int tmp = 0, res = 1, pre = 1;

for(int i = 3; i <= n; i++){

tmp = res;

res = res + pre;

pre = tmp;

}

return res;

}

}

这里是用变量来存储中间的值,也可以使用一个数组把中间结果全部都存储起来,这样就可以得到整个数列的值了。这个也是很多动态规划使用的方法,先写出暴力求解的方法,再通过中间变量修改成动态规划。

O(logN)

logN的实现主要是第N的值直接可以通过矩阵乘法算出来。

1cf75854f3fe9431a6c387cdb454c74c.png

所以只要计算出矩阵的n-2次方就可以计算出第N项的值了。怎么把一个矩阵的n次方在logN的时间内算出来了。

这里以整数为例,假设求10的64次方,假如一次一次的剩是需要剩64次的,时间复杂度是O(N)。但是10**64 = 10**32 X 10**32,这里我们只需要算出10的32次方,32次方可以通过16次方算出来,8,4..2..1, 这样只需要计算6次就可以了。

public static int getFib(int n){ if (n < 1) { return 0; } else if(n == 1 || n ==2){ return 1; } else { int [][] base={{1,1},{1,0}}; int [][] res=matrixPower(base,n-2); return res[0][0]+res[1][0]; }}//递归版本 public static int[][] matrixPower(int[][] m,int p){ if(p==0) {  return null; } else if (p==1) {  return m; } else { //这里也可以修改成非递归的方式  int[][] res=matrixPower(m, p/2); //如果是偶数次方,直接就是2分之次方相乘 res = muliMatrix(res,res); //如果是奇数还需要再乘个数 if(p % 2 == 1){ res = muliMatrix(res, m); } return res;  } }//非递归版本 public static int[][] matrixPower(int[][] m,int p){   int[][] res = new int[m.length][m[0].length];  for (int i = 0; i < res.length; i++) {  res[i][i] = 1;  }  int[][] tmp = m;  for (; p != 0; p = p/2) { if (p % 2 == 1) { res = muliMatrix(res, tmp); } tmp = muliMatrix(tmp, tmp); } return res; }  public static int[][] muliMatrix(int[][] m1, int[][] m2) { int[][] res = new int[m1.length][m2[0].length]; for (int i = 0; i < m1.length; i++) { for (int j = 0; j < m2[0].length; j++) { for (int k = 0; k < m2.length; k++) { res[i][j] += m1[i][k] * m2[k][j]; } } } return res; }

希望对大家有所帮助,有帮助记得点赞哦!可以关注下,后面持续分享编程类的文章,谢谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值