方法一:普通递归
class Solution {
public int fib(int n) {
if(n == 0){
return 0;
}else if(n == 1){
return 1;
}
return (fib(n-1)+fib(n-2))%1000000007;
}
}
由于递归的深度太深,这种方式是超时的。
方法二:记忆递归
由于计算过程中,有很多的值是重复计算的,因此可以使用一个长度为n+1的数组来对计算的结果进行保存。
class Solution {
public int fib(int n) {
if(n <= 1) return n;
int[] f = new int[n+1];
f[0] = 0;
f[1] = 1;
for(int i = 2;i<f.length;i++){
f[i] = (f[i-1] + f[i-2])%1000000007;
}
return f[n];
}
}
class Solution {
public int fib(int n) {
int a = 0, b = 1, sum;
for(int i = 0; i < n; i++){
sum = (a + b) % 1000000007;
a = b;
b = sum;
}
return a;
}
}
方法三:动态规划
斐波那契数列的表达式天生就是一个很好的转移方程,F(n+1) = F(n)+F(n-1),因此可以使用动态规划的方法来对斐波那契数列求和。
// 动态规划的四个步骤
public int fib(int n) {
if (n <= 1) return n;
// 1. 定义状态数组,dp[i] 表示的是数字 i 的斐波那契数
int[] dp = new int[n + 1];
// 2. 状态初始化
dp[0] = 0;
dp[1] = 1;
// 3. 状态转移
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
// 取模
dp[i] %= 1000000007;
}
// 4. 返回最终需要的状态值
return dp[n];
}
会发现其实和记忆递归的代码是差不多的,但是这里面包含了动态规划的思想在其中。