LeetCode 746. 使用最小花费爬楼梯 | Python

746. 使用最小花费爬楼梯


题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/min-cost-climbing-stairs/

题目


数组的每个索引作为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i](索引从0开始)。

每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。

您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。

示例 1:

输入: cost = [10, 15, 20]
输出: 15
解释: 最低花费是从cost[1]开始,然后走两步即可到阶梯顶,一共花费15。

示例 2:

输入: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
输出: 6
解释: 最低花费方式是从cost[0]开始,逐个经过那些1,跳过cost[3],一共花费6。

注意:

  1. cost 的长度将会在 [2, 1000]
  2. 每一个 cost[i] 将会是一个Integer类型,范围为 [0, 999]

解题思路


思路:动态规划

先审题,题目给定一个数组 c o s t cost cost,数组每个索引表示一个阶梯,第 i i i 个元素 c o s t [ i ] cost[i] cost[i] 表示需要花费的体力(索引从 0 开始)。

先看这句话【每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。】,是个人觉得比较有歧义的地方。下面我说一下个人的理解。

这里爬上一个阶梯需要花费对应的体力值,其中这里对应的体力值,笔者将其理解为所爬上的这个阶梯对应的体力花费值。举个例子:

      阶梯: 0 1 2 3
所花体力值: 2 3 4 5

假设要爬上第 2 2 2 个阶梯,在这里,要么从第 0 0 0 阶梯爬两个阶梯,要么从第 1 1 1 个阶梯爬一个阶梯。

在这里,根据前面所理解的含义,在这里爬到第 2 2 2 阶梯花费的总体力值应该分为以下两种情况:

  • 从第 0 0 0 阶梯爬两个阶梯,总花费体力值为:第 0 0 0 阶梯跟第 2 2 2 阶梯所花体力值之和。这里是 2 + 4 2+4 2+4
  • 从第 1 1 1 个阶梯爬一个阶梯,总花费体力值为:第 0 0 0 阶梯跟第 1 1 1 阶梯所花体力值之和。这里是 3 + 4 3+4 3+4

笔者这个理解是指踏至当前阶梯时,就需要花费当前阶梯对应的体力值。

那么现在的问题就是要求到楼顶的最小花费体力是多少,我们用动态规划的思路来解决。

状态定义

d p [ i ] dp[i] dp[i] 表示到达第 i i i 个阶梯最小花费体力值。

状态转移

题目已经说明 c o s t cost cost 的长度是在区间 [ 2 , 1000 ] [2, 1000] [2,1000],那么到达第 i i i 个阶梯,要么是从 i − 1 i-1 i1 阶梯爬一个阶梯,要么是从 i − 2 i-2 i2 阶梯爬两个阶梯,求两种方案中的较小值。这里根据前面所解释的,按照踏至阶梯就应该加上当前阶梯对应的需花费体力值,对应的转移方程如下:
d p [ i ] = m i n ( d p [ i − 1 ] + c o s t [ i ] , d p [ i − 2 ] + c o s t [ i ] ) dp[i] = min(dp[i-1]+cost[i], dp[i-2]+cost[i]) dp[i]=min(dp[i1]+cost[i],dp[i2]+cost[i])
即是:
d p [ i ] = m i n ( d p [ i − 1 ] , d p [ i − 2 ] ) + c o s t [ i ] dp[i]=min(dp[i-1], dp[i-2]) + cost[i] dp[i]=min(dp[i1],dp[i2])+cost[i]

状态初始化

题目中说明,开始可以选择从索引为 0 0 0 或者 1 1 1 的元素作为初始阶梯,按照踏至阶梯就应该加上当前阶梯对应的需花费体力值。那么此时:

  • d p [ 0 ] = c o s t [ 0 ] dp[0] = cost[0] dp[0]=cost[0]
  • d p [ 1 ] = c o s t [ 1 ] dp[1] = cost[1] dp[1]=cost[1]

这个思路中,到达楼顶时也应该计算楼层顶部对应的花费体力值。但根据示例,顶层其实是没有列出花费的体力值。假设 c o s t cost cost 数组的长度为 n n n 时,索引对应的是第 0 0 0 阶梯到第 n − 1 n-1 n1 个阶梯,其中第 n n n 个阶梯表示的顶部,由于顶层没有列出体力值,根据转移方程,最终转而求 d p [ n − 1 ] dp[n-1] dp[n1] d p [ n − 2 ] dp[n-2] dp[n2] 两者的最小值即可。

具体的代码实现如下。

class Solution:
    def minCostClimbingStairs(self, cost: List[int]) -> int:
        n = len(cost)
        # dp 数组
        dp = [0] * n
        # 初始化
        dp[0] = cost[0]
        dp[1] = cost[1]
        # 遍历填充
        for i in range(2, n):
            dp[i] = min(dp[i-1], dp[i-2]) + cost[i]
        # 返回 n-2 和 n-1 两者对应的较小值
        return min(dp[n-1], dp[n-2])

这里也提一下在官解中提供的思路,其实是指踏出当前阶梯时,才需要将当前阶梯对应的体力值加上。还是沿用前面的例子:

      阶梯: 0 1 2 3
所花体力值: 2 3 4 5

按照官方题解提供的思路,假如现在要从第 2 2 2 阶梯爬到第 3 3 3 阶梯时,求花费的总体力值?

其中这里设定是由第 0 0 0 阶梯爬至第 2 2 2 阶梯的,那么此时爬至第 2 2 2 阶梯花费的体力应该是从第 0 0 0 阶梯踏出,计算对应的体力值 2 2 2。第 2 2 2 阶梯到第 3 3 3 阶梯,这里从第 2 2 2 阶梯踏出,总体力值应该是前面的体力值 2 2 2 加上第 2 2 2 阶梯对应的体力值 4 4 4,这里是 2 + 4 2+4 2+4

这就是跟笔者所述不同的地方,这里是仅在踏出阶梯的时候才计算体力值。

具体的思路可以查看下官方题解

欢迎关注


公众号 【书所集录


如有错误,烦请指出,欢迎指点交流。如果觉得写得还可以,麻烦点个赞,谢谢。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值