同样的类型的题还有兔子繁殖的问题。
此题可以用丰富的解法来解答。
考察知识:[递归],[记忆化搜索],[动态规划], [递推]。
难度:一星
1 分治
分治思想简述
当一个问题规模较大且不易求解的时候,就可以考虑将问题分成几个小的模块,再逐一解决;
分治思想一般都会和递归一起使用,因为采用分治思想处理问题,其各个小模块通常具有与大问题相同的结构,这种特性也使递归技术有了用武之地。
所以,分治是一种思想,递归是一种技术!
1.1 分治 | 递归
大量重复计算,超时!
迭代 和 递归
对比两种实现方式,迭代和递归的区别是:迭代使用的是循环结构,递归使用的是选择结构;
使用递归能使程序的结构更清晰、更简洁、更容易让人理解,从而减少读懂代码的时间;
但是大量的递归调用会创建函数的副本,会消耗大量的时间和内存,而迭代则不需要;
递归函数分为调用和回退阶段,递归的回退顺序是它调用顺序的逆序。
public class Solution {
public int Fibonacci(int n) {
if(n<=1) return n;
return Fibonacci(n-1) + Fibonacci(n-2);
}
}1.2递归优化:记忆化搜索
用成员变量数组装着算过的数。 依旧反复递归调用自己,但用一个 if 判断来截断运算!!
public class Solution {
int ans[] = new int[40];
public int Fibonacci(int n) {
if(n<=1) return n;
if (ans[n]!=0) return ans[n];// 减少递归次数的关键。
return ans[n]= Fibonacci(n-1) + Fibonacci(n-2);
}
}2 动态规划
动态规划类似分治,同样是将原问题分解成子问题,通过求解子问题而得到原问题的解。但不同的是,动态规划是自底向上分解,并且会保存子问题的解,在需要时可直接拿过来使用,这一点是区别于分治的。
int Fibonacci(int n) {
int ans[] = new int[40];
ans[1]=1;
for (int i=2; i<=n; ++i) {
ans[i] = ans[i-1] + ans[i-2];
}
return ans[n];
}2.1 动态规划优化:递推
我比较擅长这个。
public class Solution {
public int Fibonacci(int n) {
if(n == 0) return 0;
}else if(n == 1) return 1;
int sum = 0;
int two = 0;
int one = 1;
for(int i=2;i<=n;i++){
sum = two + one;
two = one;
one = sum;
}
return sum;
}
}2.2递推: 还可以优化,用更少的变量
这个一定要学习到。 用两个指针就可以完成遍历。
public class Solution {
public int Fibonacci(int n) {
if(n == 0) return 0;
if(n == 1) return 1;
int sum = 1;
int one = 0;
for(int i=2;i<=n;i++){ //找规律找出来的精华。
sum = sum + one;
one = sum - one;
}
return sum;
}
}
京公网安备 11010502036488号