题目描述:
示例 1:
示例 2:
题目分析:
- f(0) = 0, f(1) = 1, f(n) = f(n - 1) + f(n - 2);
- n > 1
思路一:
代码实现:
class Solution {
public int mod = 1000000007;
public int fib(int n) {
return dfs(n);
}
public int dfs(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
int num = (dfs(n - 1) + dfs(n - 2)) % mod;
return num;
}
}
思路二:
按照题目中的公式,f(5) = f(4) + f(3),f(4) = f(3) + f(2),f(3) = f(2) + f(1), 可以看出来,很多元素会被重复计算,例如f(5)里面f(3)会计算一次,f(4)里面f(3)又会计算一次,可以使用一个数组将已经计算的f(n)保存起来,避免重复计算。
代码实现:
class Solution {
public int[] arr;
public int mod = 1000000007;
public int fib(int n) {
arr = new int[n + 1];
return dfs(n);
}
public int dfs(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
if (arr[n] != 0) { // 已经计算过,直接返回
return arr[n];
}
int num = (dfs(n - 1) + dfs(n - 2)) % mod;
arr[n] = num;
return num;
}
}
思路三:
因为f(n) = f(n - 1) + f(n - 2),直接就可以写出状态转换方程
代码实现:
class Solution {
public int mod = 1000000007;
public int fib(int n) {
int[] dp = new int[n + 1];
if (n == 0) return 0;
if (n == 1) return 1;
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = (dp[i - 1] + dp[i - 2]) % mod;
}
return dp[n];
}
}
思路四:
观察思路三,可以发现,dp[n]的值只与dp[n - 1],dp[n - 2]相关,因此没必要使用数组,只需要保存上一个以及上上一个点值就可以了。
代码实现:
class Solution {
public int mod = 1000000007;
public int fib(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
int next = 1; // 上一个值
int next_next = 0; // 上上一个值
int result = 0;
for (int i = 2; i <= n; i++) {
result = (next + next_next) % mod; // f(n) = f(n - 1) + f(n - 2);
next_next = next;
next = result;
}
return result;
}
}