文章目录
- 题目描述
- 简化题目
- 思路分析
- 完整代码
题目描述
给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例 1:
输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。
支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15 。
示例 2:
输入: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 。
简化题目
这题目描述的就很诡异。理清楚花费顺序比写出代码要难哈哈。
简单来说,cost = [10,15,20] 题目给了这个数组,楼顶在最后 cost = [10,15,20] X。
也就是我标的X的地方是楼顶,可以从0号或者1号位置开始,每次可以选择走1步或者2步,走的时候要花费当前数值的体力。
这里何时花费体力值比较绕,总的来说,第一步必花费体力值,后面到哪里就直接花掉。
顺序步骤:
即 第一步花费 -> 选择走几步 -> 到达某个点(直接花费掉该点的体力值)->继续选择走几步 -> 到达某个点(继续花体力)
且最后一步到达顶点的台阶不需要花费体力 这点很重要
比如cost = [10,15,20] 从1号位置开始走两步,直接能达到X的位置,花费15。为最小花费。
思路分析
动态规划五步走:
1.确定dp[i]含义;
dp[i] 表示到达第i个台阶所要花费的最小体力值。
2.确定递推公式:
到达第i个台阶只能从i-1迈一步上来,或者从i-2迈两步上来。显然选择花费最小的方案走。
得到递推公式:
dp[i] = min(dp[i-1],dp[i-2]) + cost[i]。
这里为啥要加上cost[i],,因为题目中说了:每当你爬上一个阶梯你都要花费对应的体力值
3.初始化dp数组;
根据上面的递推公式,要初始化前两个。
dp[0] = cost[0]
dp[1] = cost[1]
4.确定遍历顺序:
由递推公式可知:
第一个和第二个确定第三个。所以正向遍历。
5.模拟dp看结果:
用示例2,cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]:
相应dp数组:[1, 100, 2, 3, 3, 103, 4, 5, 104, 6]
所以要返回的值是 dp[-2]和dp[-1] 的最小值。 想象一下前面的定义逻辑,最后一步是不需要花费的,
这里其实也可以理解为:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]X, 楼顶是X,也就是到X可以选择 dp[-2]和dp[-1] ,显然选小的。但是已经不需要再扣费了,这就是这道题的诡异之处,直接理解成最后一步不需要扣费就行了。
完整代码
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
dp = [0] * len(cost)
dp[0] = cost[0]
dp[1] = cost[1]
for i in range(2,len(cost)):
dp[i] = min(dp[i-1],dp[i-2]) + cost[i]
return min(dp[-1],dp[-2])