斐波那契数列问题的递归和动态规划

1.给定整数N,返回斐波那契数列的第N项。
分析:斐波那契数列:1,1,2,3,5,8,…
F(1)=1; F(2)=1;F(N)=F(N-1)+F(N-2)
由上述的式子,我给出了第一种递归解法
(1)

 public static int fN(int n){
        if(n<1){
            return 0;
        }
        if(n==1||n==2){
            return 1;
        }

        return  fN(n-1)+fN(n-2);
    }

但是,此解法的时间复杂度为O(2^N),很显然,不是我们想要的,为此,我引入了第二种方法:
(2)斐波那契数列可以从左到右推出每一项的值
2=1+1; 3=2+1;…

public static int fN(int n) {
        int result = 1;
        int pre = 1;
        int temp = 0;
        if (n < 1) {
            return 0;
        }
        if (n == 1 || n == 2) {
            return 1;
        }
        for(int i=3;i<=n;i++) {
            temp = result;
            result = result + pre;
            pre = temp;
        }
        return result;
    }

观察上述代码,时间复杂度为O(N),依然不是我们想要的最优结果,我们希望用一个方法它的时间复杂度为O(logN),那如何实现呢?
在此,我引入了第三种方法:
(3)F(N)=F(N-1)+F(N-2),是一个二阶递推数列,则就可以用矩阵的乘法的形式表示:
(F(N),F(N-1))=(F(N-1),F(N-2))O(22)
O(2*2):表示2行2列的状态矩阵
由前四项解得;状态矩阵为:{{1,1,},{1,0}}
推导过程如下: 在这里插入图片描述
代码实现:

  public int[][] muliMatrix(int[][] m1,int[][] m2){
        int[][] result=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++){
                    result[i][j]+=m1[i][k]*m2[k][j];
                }
            }
        }
        return  result;
    }
    //求矩阵的n 次方
    public int[][] Powermatrix(int[][] m, int n){
        int[][] result=new int[m.length][m[0].length];
        for(int i=0;i<result.length;i++){
            result[i][i]=1;       //先把result设为单位矩阵,1
        }
        int[][] temp=m;
        for(;n!=0;n=n>>1){
            if((n&1)!=0){
                result=muliMatrix(result,temp);
            }
            temp=muliMatrix(temp,temp);
        }
        return  result;
    }
    public  int fN(int n){
        if(n<1){
            return 0;
        }
        if(n==1||n==2){
            return 1;
        }
        int[][] m={{1,1},{1,0}};
        int[][] result=Powermatrix(m,n-2);
        return result[0][0]+result[1][0];
    }

此方法的时间复杂度为:O(logN)
因为相当于将问题转换成了求一个矩阵N次方的问题。

补充问题:
输入一个整数n,算最少需要多少步它能变成斐波那契数列
分析:
要想算最少的步数,则:
第一步:找到一个大于等于整数n的斐波那契数记为x
第二步:找到它的前一个斐波那契数记为y
第三步:比较|x-n|,|y-n|,得到的最小的便为我们需要的结果。
程序实现:

public class FiBoNac {
    public static int fN(int n){
        if(n<1){
            return 0;
        }
        if(n==1||n==2){
            return 1;
        }

        return  fN(n-1)+fN(n-2);
    }
    public static int getStep(int n){
        int m=0;
        int x=0;
        while(m>=0){
            if(fN(m)>=n){
                x=fN(m);
                break;
            }
            else{
                m++;
            }
        }
        int y=fN(m-1);
        return Math.min(abs(y-n),abs(x-n));
    }

    public static void main(String[] args) {
        Scanner scan=new Scanner(System.in);
        int n=scan.nextInt();
        System.out.println(getStep(n));

    }
}

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值