0
点赞
收藏
分享

微信扫一扫

leetcode(力扣) 746. 使用最小花费爬楼梯 ( 动态规划 & 解析诡异题目 )


文章目录

  • ​​题目描述​​
  • ​​简化题目​​
  • ​​思路分析​​
  • ​​完整代码​​

题目描述

给你一个整数数组 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])


举报

相关推荐

0 条评论