【LeetCode 动态规划专项】使用最小花费爬楼梯(746)

1. 题目

数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 0 0 开始)。每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 0 0 1 1 1 的元素作为初始阶梯。

1.1 示例

  • 示例 1 1 1

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

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

1.2 说明

1.3 提示

  • cost 的长度范围是 [2, 1000]
  • cost[i] 将会是一个整型数据,范围为 [0, 999]

1.4 进阶

你可以进一步输出花费最小时所爬阶梯的下标么?

2. 动态规划

2.1 分析

实际上,这道题目只要认真理解清楚题目的含义就很好解答,其中最重要的是要理解什么叫爬到楼顶,其实当你最后一次站上了下标为 i - 1 或下标为 i 的阶梯时,之后再跨一次就到达楼顶(这里只有比楼顶低一个及以上数量台阶高度的位置才被称为阶梯)了;另外跨台阶是不需要消耗体力的,只有站上台阶才会消耗体力,更重要的是站上楼顶也不会消耗体力。

2.1.1 定义状态

使用 dp[i] 表示为了站上下标为 i 的阶梯所耗费的最小体力。

2.1.2 基本状态

根据状态的含义,显然应该有 dp[0] = cost[0]dp[1] = cost[1]

2.1.3 状态转移

为了能站上第 i 级阶梯,先前可能站在第 i - 1 级阶梯或第 i - 2 级阶梯,因此状态转移方程为: min(dp[i - 1], dp[i - 2]) + cost[i]

2.2 解答

根据上述分析给出如下解答:

from typing import List


class Solution:
    def min_cost_climb_stairs(self, cost: List[int]) -> int:
        if len(cost) == 2:
            return min(cost[0], cost[1])
        dp = [0 for _ in range(len(cost))]
        dp[0] = cost[0]
        dp[1] = cost[1]
        for i in range(2, len(cost)):
            dp[i] = min(dp[i - 1] + cost[i], dp[i - 2] + cost[i])
        return min(dp[-1], dp[-2])


def main():
    cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
    sln = Solution()
    print(sln.min_cost_climb_stairs(cost))  # 6


if __name__ == '__main__':
    main()

2.3 复杂度

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

实际上,可以继续优化上述代码,使得空间复杂度下降至 O ( 1 ) O(1) O(1)

from typing import List


class Solution:
    def space_efficient_min_cost_climb_stairs(self, cost: List[int]) -> int:
        prev, cur = cost[0], cost[1]
        for i in range(2, len(cost)):
            prev, cur = cur, min(prev, cur) + cost[i]
        return min(prev, cur)


def main():
    cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
    sln = Solution()
    print(sln.space_efficient_min_cost_climb_stairs(cost))  # 6


if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/weixin_37780776/article/details/120803339