斐波拉切数列 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=Fibn−1+Fibn−2代码也很好实现:
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} Fibn−1与 F i b n − 2 Fib_{n−2} Fibn−2有关系,所以不用数组存,用字母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=pan−1+qan−2的特例,不过 a n = p a n − 1 + q a n − 2 a_n=pa_{n−1}+qa_{n−2} an=pan−1+qan−2有点难,我们需要一点点前置知识:
step1: a n = p a n − 1 a_n=pa_{n−1} an=pan−1,这是个等比数列,直接过掉。
解: 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=pan−1=p2an−2=…=pn−1a1
step2: a n = p a n − 1 + q a_n=pa_{n−1}+q an=pan−1+q,尝试转化为等比数列。
解:待定系数。令 a n + t = p ( a n − 1 + t ) a_n+t=p(a_{n−1}+t) an+t=p(an−1+t)解出t即可。
step 3: a n = p a n − 1 + q a n − 2 a_n=pa_{n−1}+qa_{n−2} an=pan−1+qan−2。
要讲明白特征方程是怎么回事实在是太麻烦了,笔者手写了三页,但最后字迹过于丑陋,不宜展示。
我认为这里写的不错,可以参考。
综上,通项公式为:
借鉴 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;
}
}