剑指offer - 斐波那契数列(Java实现)

题目链接:https://www.nowcoder.com/practice/c6c7742f5ba7442aada113136ddea0c3?tpId=13&&tqId=11160&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

  思路一:递归,如图递归的来计算第 n 个斐波那契数。
斐波那契递归

public class Solution {
    public int Fibonacci(int n) {
        if(n == 0) return 0;
        if(n == 1) return 1;
        return f(n);
    }
    public static int f(int n) {
        if(n == 0) return 0;
        if(n == 1) return 1;
        return f(n - 1) + f(n - 2);
    }
}

  思路二:记忆化数组,从递归方法中的图来看,在递归的过程中,我们需要进行大量的重复计算,这样就大大降低了程序的执行效率,我们可以使用一个记忆化数组来保存已经计算过的数组,这个就可以降低程序的时间复杂度。

public class Solution {
    static int[] F = new int[40];
    public int Fibonacci(int n) {
        for(int i = 0; i < 40; ++ i) F[i] = 0;
        if(n == 0) return 0;
        if(n == 1) return 1;
        return f(n);
    }
    public static int f(int n) {
        if(F[n] != 0) return F[n];
        if(n == 0) return 0;
        if(n == 1) return 1;
        return F[n] = f(n - 1) + f(n - 2);
    }
}

  思路三:递推,f[n] = f[n - 1] + f[n - 2];

public class Solution {
    static int[] F = new int[40];
    public int Fibonacci(int n) {
        F[0] = 0; F[1] = 1;
        for(int i = 2; i <= n; ++ i) {
            F[i] = F[i - 1] + F[i - 2];
        }
        return F[n];
    }
}

  思路四:矩阵快速幂。 ,我们令:
    
那么我们需要找到的矩阵 A 就满足:
      
又因为:
    
所以:
    
即:
    
综上所述:
    


我们用矩阵快速幂求出后,结果矩阵的第一行与上面公式中最后的做矩阵乘法即是最终结果。

快速幂:https://blog.nowcoder.net/n/f93bed69e38f474a839cb5105d0babc2

public class Solution {
    public int Fibonacci(int n) {
        if(n == 0) return 0;
        if(n == 1) return 1;
        int[][] a = new int[2][2];
        init(a);
        int[][] ans = quickPow(a, n - 1);
        return ans[0][0];
    }
    static int[][] init(int[][] a) {
        a[0][0] = 1; a[0][1] = 1;
        a[1][0] = 1; a[1][1] = 0;
        return a;
    }
    static int[][] quickPow(int[][] a, int b) {
        int[][] ans = new int[2][2], res = new int[2][2];
        init(ans); init(res);
        ans[0][1] = 0; ans[1][0] = 0; ans[1][1] = 1;
        while(b > 0) {
            if(b % 2 == 1) ans = mul(ans, res);
            res = mul(res, res);
            b >>= 1;
        }
        return ans;
    }

    static int[][] mul(int[][] a, int[][] b) {
        int[][] z = new int[2][2];
        for(int i = 0; i < 2; ++ i) {
            for(int j = 0; j < 2; ++ j) {
                z[i][j] = 0;
                for(int k = 0; k < 2; ++ k) {
                    z[i][j] += a[i][k] * b[k][j];
                }
            }
        }
        return z;
    }
}
【剑指offer】题目全解 文章被收录于专栏

本专栏主要是刷剑指offer的题解记录

全部评论

相关推荐

11-09 14:54
已编辑
华南农业大学 产品经理
大拿老师:这个简历,连手机号码和照片都没打码,那为什么关键要素求职职位就不写呢? 从上往下看,都没看出自己到底是产品经理的简历,还是电子硬件的简历? 这是一个大问题,当然,更大的问题是实习经历的描述是不对的 不要只是去写实习流程,陈平,怎么去开会?怎么去讨论? 面试问的是你的产品功能点,是怎么设计的?也就是要写项目的亮点,有什么功能?这个功能有什么难处?怎么去解决的? 实习流程大家都一样,没什么优势,也没有提问点,没有提问,你就不得分 另外,你要明确你投的是什么职位,如果投的是产品职位,你的项目经历写的全都是跟产品无关的,那你的简历就没用 你的面试官必然是一个资深的产品经理,他不会去问那些计算机类的编程项目 所以这种四不像的简历,在校招是大忌
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务