代码随想录第二十天:动态规划、斐波那契数列、爬楼梯、最小体力爬楼梯
1.动态规划理论
理论讲解链接:代码随想录 (programmercarl.com)
对于动态规划问题,可以拆解为如下五步曲
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
2.斐波那契数列
dp数组元素的含义是对应斐波那契数列的元素。
递推公式F(n) = F(n - 1) + F(n - 2)。
初始化F(0) = 0,F(1) = 1。
遍历顺序从前向后。
代码如下:
class Solution{
public:
int fib(int n) {
if (n == 0 || n == 1) return n;
vector<int> dp(n + 1, 0);
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i < n + 1; ++i) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
};
3.爬楼梯
本题的关键逻辑是当前阶梯,可以由上一节阶梯走一步或者由上上一节阶梯走两步得来,所以走到当前阶梯的方法是去上一节阶梯的方法加上去上上一节阶梯的方法。
因此得到递推公式:F(n) = F(n - 1) + F(n - 2),所以本题所求就是斐波那契数列。
代码如下:
class Solution {
public:
int climbStairs(int n) {
if (n == 0 || n == 1) return n;
vector<int> dp(n + 1, 0);
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i < n + 1; ++i) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
};
3.最小代价爬楼梯
本题为每个楼梯添加了攀爬的代价,可以选择从前两层开始爬。
爬到每层的代价是爬到前一层的代价加上前一层继续前进花费的代价,或者是前两层的代价加上继续前进的代价,最小代价取二者最小值即可。
因此递推公式:dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
代码如下:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
if (cost.size() == 0 || cost.size() == 1) return 0;
vector<int> dp(cost.size(), 0);
for (int i = 0; i < dp.size() ; ++i) {
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
}
return dp[cost.size() - 1];
}
};