经典题目,用了两种方法实现。第一种是循环,不要搞数组浪费内存,三个值就行了。从i=2遍历到i==n。
第二种是递归+dp,因为这题直接递归会费时,比如计算F(5)=F(4)+F(3),计算F(4)=F(3)+F(2),F(3)被重复计算。为了避免重复计算,开一个数组dp用来保存已经计算过的结果。递归有递归边界,当n ==0就返回0,1就返回1。预先将dp全赋值-1,如果dp[n]的值不为-1,就直接返回结果。如果为-1,就计算dp[n]=F(n-1) + F(n-2),然后返回dp[n]
class Solution {
public:
int dp[40] = {-1};
int Fibonacci(int n) {
/*循环
f(n==0) return 0;
if(n==1) return 1;
int first = 0;
int second = 1;
int res = 0;
for(int i = 2; i <= n; ++i){
res = first + second;
first = second;
second = res;
} */
//递归+动态规划
for(int i = 0; i < 40; ++i){
dp[i] = -1;
}
dp[0] = 0;
dp[1] = 1;
if(n == 0) return 0;
if(n == 1) return 1;
return F(n-1) + F(n-2);
}
int F(int n){
if(n == 0) return 0;
if(n == 1) return 1;
if(dp[n] != -1) return dp[n];
else{
dp[n] = F(n-1) + F(n-2);
return dp[n];
}
}
};
确实实力进步很多
法一:dp,记录前两个几个
法二:记忆化搜索
class Solution {
public:
int dfs(int n){
if(mem[n] != -1) return mem[n];
mem[n] = (dfs(n-1) + dfs(n-2))%1000000007;
return mem[n];
}
int fib(int n) {
//dp就行,先写迭代版本,只和前两位有关系
//状态转移:dp[i] = dp[i-1] + dp[i-2]
if(n <= 1) return n;
// int pre1 = 0, pre2 = 1;
// int res = 0;
// for(int i = 2; i <= n; ++i){
// res = (pre1 + pre2)%1000000007;
// pre1 = pre2;
// pre2 = res;
// }
// return res;
//递归版本,用的是记忆化搜索
//不要在原函数递归,原函数是用来初始化的
mem.resize(n+1,-1);
mem[0] = 0;
mem[1] = 1;
return dfs(n);
}
private:
vector<int> mem;
};