动态规划的解题步骤
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
509. 斐波那契数
按照动态规划的解题步骤,再根据题意,可以知道dp数组的下标表示第几位的斐波那契数,dp数组存储的是整个斐波那契数列。至于递推公式以及dp数组如何初始化,题目已经给出
F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1
因为每一位斐波那契数都要依赖于前两位的和,所以自然要从前向后遍历。
class Solution {
public:
int fib(int n) {
if(n == 0)return 0;
if(n == 1)return 1;
int F[n+1];
F[0] = 0;
F[1] = 1;
for(int i = 2;i <= n;i++){
F[i] = F[i-1] + F[i-2];
}
return F[n];
}
};
70. 爬楼梯
按照动态规划的解题步骤,先确定dp数组,既然左后要求有多少种不同的方法可以爬到楼顶那么dp数组就可以用来存储到达每一个台阶有多少种方法,i即代表第几个台阶,由于在每个台阶上我可以选择向上走1步还是2步,所以能够一步走到当前台阶的,只能是当前台阶的上一个台阶和上上个台阶,而一步走到当前台阶不算另外的方法,所以递推公式
result[i] = result[i-1] + result[i-2]
那么如何初始化?试想我们要走到第一个台阶,就只有一种办法就是走一步,我们要走到第二个台阶有两种方法,一种是直接走两步,一种是走一步再走一步。根据递推公式,不需要去推导走到第三个台阶的方法数,所以初始化完成。同上一题,由于要根据前面两个台阶的值来确定当前台阶的值,所以要从前向后遍历。
class Solution {
public:
int climbStairs(int n) {
if(n == 1)return 1;
int result[n+1];
result[1] = 1;
result[2] = 2;
for(int i = 3;i <= n;i++){
result[i] = result[i-1] + result[i-2];
}
return result[n];
}
};
746. 使用最小花费爬楼梯
按照动态规划的解题步骤, 根据题目要求:请你计算并返回达到楼梯顶部的最低花费。可以确定dp数组存的就是到达每一个台阶的最低花费,再根据上一题爬楼梯的递推公式,所以最低花费只需要考虑上上个台阶和上个台阶的最低花费加上它们向上爬楼梯的花费取最小值即可
dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
因为可以选择从下标为 0
或下标为 1
的台阶开始爬楼梯。所以初始化也很容易。
dp[0] = 0;
dp[1] = 0;
因为是爬楼梯问题,所以肯定是从前向后遍历。整体代码如下:
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
if(cost.size() == 0 || cost.size() == 1)return 0;
int dp[cost.size()+1];
dp[0] = 0;
dp[1] = 0;
for(int i = 2; i <= cost.size();i++){
dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[cost.size()];
}
};