个人主页:平行线也会相交
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【手撕算法系列专栏】【LeetCode】
🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助
🍓希望我们一起努力、成长,共同进步。
点击直接跳转到该题目
目录
- 🍞题目描述
- 🥟算法原理(解法一)
- 🍭算法原理(解法二)
- 🍰代码实现(解法1)
- 🍡代码实现(解法2)
- 🍋总结
🍞题目描述
给你一个整数数组 cost
,其中 cost[i]
是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例一:
输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。
支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15 。
示例二:
输入:cost = [1,100,1,1,1,100,1,1,100,1] 输出:6 解释:你将从下标为 0 的台阶开始。
- 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
- 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
- 支付 1 ,向上爬一个台阶,到达楼梯顶部。 总花费为 6 。
🥟算法原理(解法一)
步骤1:状态表示
根据题目要求,以i位置为结尾,
dp[i]
表示到达i位置所需要的最小花费。
步骤2:状态转移方程
推导状态转移方程时,可以利用
i
位置之前或者之后的状态来进行状态转移方程的推导。以后在做动态规划的题目时,利用i
位置之前或者之后的状态来进行状态转移方程的推导是一个很常见的思路方向。
现在我们进行题目的分析,我们知道dp[i]表示到达i位置需要的最小花费,其中到达i位置分为两种情况。我们先以i位置为结尾(以i位置为起点来进行分析是下面的解法二),根据最近的一步来进行题目的分析
,总共分为两种情况。
情况一:从i-2位置跳两步到达i位置。
情况二:从i-1位置跳一步1到达i位置。
我们再来解释一下情况1、2:
情况一
:我们如果想要知道到达i位置所需要的最小花费的话,首先要知道到达i-1位置所需要的最小花费(即dp[i-1]表示到达i-1位置所需要的最小花费),而cost[i-1]表示支付完cost[i-1]从i-1位置向上爬所需要的费用。
情况二
:i-2位置所需要的最小花费(即dp[i-2]表示到达i-2位置所需要的最小花费),而cost[i-2]表示支付完cost[i-2]从i-2位置向上爬所需要的费用。
最终,推导出状态转移方程dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
。
步骤3:初始化
初始化依然是保证填表的时候防止越界问题的产生来保证填表的时候不越界。
步骤4:填表顺序
如果想要知道dp[i]的值,就需要知道dp[i-2]和dp[i-1]的值,所以需要从左往右进行填表。
步骤5:返回值
到达楼顶就是到达下标为n的地方,返回值根据题目要求来进行返回。直接返回
dp[n]
就好了。
🍭算法原理(解法二)
刚刚我们是按照以i的位置为结尾进行思考分析,现在我们按照以i的位置为开头来进行思考分析。
好了,这里我们依然按照那5个步骤进行分析,请看:
步骤1:状态表示
dp[i]表示从i位置出发到达楼顶的最小花费。
步骤2:状态转移方程
求取这里的状态转移方程的时候依然是分为两种情况:
情况一:支付cost[i],然后走1步到达i+1,最后从i+1位置出发到达终点。
情况二:支付cost[i],然后走2步到达i+2,最后从i+2位置出发到达终点。
然而最终dp[i]的取值依然是情况1、2中的最小值。
故最终的状态转移方程为:dp[i]=min(cost[i]+dp[i+1],cost[i]+dp[i+2])
步骤3:初始化
由于我们在求取dp[i]的时候需要用到dp[i+1]和dp[i+2]的值,所以我们在进行初始化的时候需要先对后面进行初始化。
这里有一个地方需要注意:dp数组的下标应该开到n-1的位置,因为下标n的位置代表楼顶,从楼顶到楼顶不需要花费。故dp数组只需要开辟n个元素个数的空间
即可。
所以初始化时只需要初始化最后两个位置的值即可:
从n-1位置走一步直接到达楼顶只需要支付cost[n-1],从n-2位置走两步直接到达楼顶只需要支付cost[n-2]。由此我们就可以根据最后两个位置的值来推导前面位置的dp值。
步骤4:填表顺序
由上一步骤我们可以知道,我们需要根据最后两个位置的值来推导前面位置的dp值,即从后往前进行赋值。填表顺序当然也是从后往前了。
步骤5:返回值
我们最初的状态是处以0位置或者1位置的状态,所以我们需要返回这两种情况(从0位置出发还是从1位置出发)中的最小值。即返回
min(dp[0],dp[1])
。
🍰代码实现(解法1)
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
//1.创建dp表
//2.初始化(防止越界)
//3.填表
//4.返回值
int n = cost.size();
vector<int> dp(n+1);
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];//下边n就是楼顶
}
};
🍡代码实现(解法2)
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
//1.创建dp表
//2.初始化
//3.填表
//4.返回值
int n = cost.size();
vector<int> dp(n);
dp[n-1]=cost[n-1],dp[n-2]=cost[n-2];
for(int i = n-3;i>=0;i--)
dp[i]=min(cost[i]+dp[i+1],cost[i]+dp[i+2]);
return min(dp[0],dp[1]);
}
};
🍋总结
利用i位置之前或者之后的状态来进行状态转移方程的推导,本文使用了两种方法来解决使用最小花费爬楼梯:
第一种思路:以i位置为结尾进行分析,dp[i]表示到达i位置所需要的最小花费。状态转移方程dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
第二种思路:以i位置为起点进行分析,dp[i]从i位置出发到达顶部所需要的最小花费。状态转移方程为dp[i]=min(cost[i]+dp[i+1],cost[i]+dp[i+2])
。
好了,本文就到这里啦!
再见啦友友们!!!