斐波拉切数列 java版本

斐波拉切数列 java版本

试求 F i b n Fib_n Fibn
样例

输入:

5
输出:

5

算法1
(暴力递推) O(n)
想要存储他,很多人会想到用一维数组存储+递推。递推初值为 F i b 0 = 0 , F i b 1 = 1 Fib_0=0,Fib_1=1 Fib0=0,Fib1=1。递推式为 F i b n = F i b n − 1 + F i b n − 2 Fib_n=Fib_{n-1}+Fib_{n−2} Fibn=Fibn1+Fibn2代码也很好实现:

public class Solution {
    
    

    public static void main(String[] args) {
    
    
        Solution solution = new Solution();
        int n = 10;
        int x = solution.fib(n);
        System.out.println(x);
    }

    public int fib(int n) {
    
    
        if (n == 0 || n == 1) {
    
    
            return n;
        }
        int[] dp = new int[n+1];
        dp[0] = 0;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
    
    
           dp[i] = (dp[i-1] + dp[i-2] ) % 1000000007;
        }
        return dp[n] % 1000000007;
    }
}

算法2
(暴力递推+空间优化) O(n)
可以将上面代码优化一下, F i b n Fib_n Fibn只和 F i b n − 1 Fib_{n−1} Fibn1 F i b n − 2 Fib_{n−2} Fibn2有关系,所以不用数组存,用字母a,b,c代替即可。代码如下:

public class Solution {
    
    

    public static void main(String[] args) {
    
    
        Solution solution = new Solution();
        int n = 10;
        int x = solution.fib(n);
        System.out.println(x);
    }

    public int fib(int n) {
    
    
        if (n == 0 || n == 1) {
    
    
            return n;
        }
        int a = 0;
        int b = 1;
        int c = 0;
        for (int i = 2; i <= n; i++) {
    
    
            c = (a + b) % 1000000007;
            a = b;
            b = c;
        }
        return c % 1000000007;
    }
}

算法3
(求递推公式) O ( 1 ) O(1) O(1)
我慢慢要显露出数竞生本色啦!

其实不难发现,斐波那契就是 a n = p a n − 1 + q a n − 2 a_n=pa_{n−1}+qa_{n−2} an=pan1+qan2的特例,不过 a n = p a n − 1 + q a n − 2 a_n=pa_{n−1}+qa_{n−2} an=pan1+qan2有点难,我们需要一点点前置知识:

step1: a n = p a n − 1 a_n=pa_{n−1} an=pan1,这是个等比数列,直接过掉。

解: a n = p a n − 1 = p 2 a n − 2 = … = p n − 1 a 1 a_n=pa_{n−1}=p_2a_{n−2}=…=p_{n−1}a_1 an=pan1=p2an2==pn1a1
step2: a n = p a n − 1 + q a_n=pa_{n−1}+q an=pan1+q,尝试转化为等比数列。

解:待定系数。令 a n + t = p ( a n − 1 + t ) a_n+t=p(a_{n−1}+t) an+t=p(an1+t)解出t即可。

step 3: a n = p a n − 1 + q a n − 2 a_n=pa_{n−1}+qa_{n−2} an=pan1+qan2

要讲明白特征方程是怎么回事实在是太麻烦了,笔者手写了三页,但最后字迹过于丑陋,不宜展示。

我认为这里写的不错,可以参考。

综上,通项公式为:

image-20210508151909789

借鉴 https://www.acwing.com/solution/content/12476/

代码

class Solution {
    
    
    public int Fibonacci(int n) {
    
    
        double a = (1 + Math.sqrt(5)) / 2;
        double qa = Math.pow(a,n);
        double b = (1 - Math.sqrt(5)) / 2;
        double qb = Math.pow(b,n);
        double res = ( (1 / Math.sqrt(5)) * (qa - qb) % 1000000007);
        return (int)res;
        
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41688840/article/details/116529158