1、遍历:在遍历的过程中就能够解决问题,只需要递归函数的参数即可。
2、子树:只有在遍历完成之后才能解决问题,还需要递归函数的返回值。(需要在后序位置写代码)
动态规划:子树 核心思想是穷举求最值
动态规划三要素:
正确的状态转移方程
具有最优子结构
存在重叠子问题(暴力穷举效率很低,需要使用备忘录(dp table)来优化穷举过程)
明确状态,明确选择,定义dp数组
回溯算法:树枝
DFS算法:节点
1、斐波那契数(难度:简单)
AC方法和对应代码
1、暴力递归穷举
重复计算太多
时间复杂度是O(2的n次方)
class Solution {
public:
//暴力递归穷举
int fib(int n) {
if(n==0 || n==1){
return n;
}
return fib(n-1)+fib(n-2);
}
};
2、带备忘录的递归解法
使用备忘录数组或者字典(这里用的数组)来记录每次已经算过的fib(n),避免重复计算
时间复杂度是O(n)
class Solution {
public:
//带备忘录的递归解法
int fib(int n) {
int nums[n+1];
memset(nums,-1,sizeof(nums));
return dp(nums, n);
}
int dp(int nums[], int n){
if(n==0 || n==1){
nums[n]=n;
}
//备忘录
if(nums[n]!=-1){
return nums[n];
}
return dp(nums,n-1)+dp(nums,n-2);
}
};
3、dp数组的迭代(递推)解法(for循环)