DP学习之爬楼梯
剑指 Offer II 088. 爬楼梯的最少成本 - 力扣(LeetCode)
1. 题目分析
可以从第0或者第1作为起始台阶、每次可以选择跳1或2步、到楼顶结束
2. 解题
a.解法一
- 状态表示
tips: 经验+题目要求。以i位置为结尾,。。。
dp[i] : 到达i位置时,最小花费
- 状态转移方程
tips: 用之前或之后的状态,推导出dp[i]的值。根据最近的一步,来划分问题
到达i位置之前:
- 从i-1位置走一步,支付cost[i-1]的花费,到i位置
- 从i-2位置走两步, 支付cost[i-2]的花费,到i位置
由于状态表示以及定义,需要选择到达i位置的最小花费
即:dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])
- 初始化
tips: 保证填表的时候不越界。i为0时,需要dp[-1]和dp[-2]会越界
题目要求:可以从0或者1下标作为初始台阶
dp[0] = dp[1] = 0
- 填表顺序
由前面的dp[i - 1],dp[i - 2]值可以推导dp[i]
从左往右(---->)
- 返回值
楼顶在n下标处
return dp[n]
代码
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
//1.创建dp表
//2.初始化
//3.填表
//4.返回值
int n = cost.size();
vector<int> dp(n + 1, 0);
for(int i = 2; i <= n; ++i)
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
return dp[n];
}
};
b.解法二
- 状态表示
以i位置为起点,。。。
dp[i] : 从i位置出发,到达楼顶,此时的最小发费
- 状态转移方程
到达i位置之后:
- 从i位置走一步,支付cost[i]的花费,到i+1位置
- 从i位置走两步, 支付cost[i]的花费,到i+2位置
由于状态表示以及定义,需要从那个位置开始(i+1、i+2)到终点的花费最小
即:dp[i] = min(dp[i + 1], dp[i + 2]) + cost[i]
- 初始化
tips: 保证填表的时候不越界。
从楼顶(n下标)到楼顶的花费为0
dp[n - 1] = cost[n - 1], dp[n - 2] = cost[n - 2]
- 填表顺序
由前面的dp[i + 1],dp[i + 2]值可以推导dp[i]
从右往左(<----)
- 返回值
根据状态定义,题目要求
return min(dp[0], dp[1])
代码
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
//1.创建dp表
//2.初始化
//3.填表
//4.返回值
int n = cost.size();
vector<int> dp(n, 0);
dp[n - 1] = cost[n - 1], dp[n - 2] = cost[n - 2];
for(int i = n - 3; i >= 0; --i)
dp[i] = min(dp[i + 1], dp[i + 2]) + cost[i];
return min(dp[0], dp[1]);
}
};
3. 总结
首先根据题目要求和经验(一般经验:以某个位置为结尾或以某个位置为起点,。。。)推导出状态表示。
根据状态表示来推状态转移方程。如果定义的状态表示不能够推导出状态转移方程,则状态表示是错误的。
新手要敢于自己定义状态表示,孰能生巧,大量做题后,状态表示的定义往往会向着正确的方向。
🦀🦀观看~~