[509. 斐波那契数]
「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战」。
题目描述
斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给定 n ,请计算 F(n) 。
示例
示例1 :
输入: n = 2
输出: 1
解释: F(2) = F(1) + F(0) = 1 + 0 = 1
示例 2:
输入: n = 3
输出: 2
解释: F(3) = F(2) + F(1) = 1 + 1 = 2
示例 3:
输入: n = 4
输出: 3
解释: F(4) = F(3) + F(2) = 2 + 1 = 3
提示:
0 <= n <= 30
思路
这可以说是年轻人的第一道动态规划题。判定一道题使用动态规划的标准是看当前状态是否依赖之前的状态,即问题由许多重复的子问题组成,判定为是之后有以下几个步骤,复习一下:
-
确定dp数组(dp table)以及下标的含义
-
确定递推公式
-
dp数组如何初始化
-
确定遍历顺序
-
举例推导dp数组
而这道题直接给出了递推公式,具体到这道题:
1、dp数组含义:即 f(n)。
2、F(n) = F(n - 1) + F(n - 2),其中 n > 1;
3 、F(0) = 0,F(1) = 1
4、依赖之前的状态,即从前往后遍历。
5、 0,1,2,3,5,8···
但是,在一开始学习编程语言的时候,常常是使用递归,也就是回溯的做法,使用递归的一般步骤:
-
确定递归函数的返回值以及参数
-
明确回溯函数终止条件
-
寻找单层搜索的过程
具体到这道题:
1、 返回值和参数:很明显题目给好了
2、 终止条件: 因为 F(0) = 0,F(1) = 1,使用当为0或1时,就需要返回。
3、单层搜素:由F(n) = F(n - 1) + F(n - 2),其中 n > 1知;需要进入F(n - 1) 和 F(n - 2) 。
代码实现
动态规划由于只是依赖前两个状态,所以可以压缩dp数组的大小
class Solution {
public:
int fib(int N) {
if (N <= 1) return N;
vector<int> dp(N + 1);
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= N; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[N];
}
};
递归:
class Solution {
public:
int fib(int N) {
if (N <= 1) return N; //终止条件
return fib(N-1)+fib(N-2); //单层搜索
}
};
总结
简要的介绍和复习了动态规划和回溯。