LeetCode 动态规划之使用最小花费爬楼梯

1,484 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目

使用最小花费爬楼梯

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

提示:

  • 2 <= cost.length <= 1000
  • 0 <= cost[i] <= 999

题解

解题分析

题解思路

  1. 该题是一个典型的动态规划题目;

  2. 假设数据的长度为 n , 则 n 个阶梯非别对应数组下标 0 到 n-1, 楼层顶部对应下标 n, 问题等于达到 n 的最小花费。

  3. 创建一个长度为 n+1 长度的数组 dp, 其中 dp[i] 表示达到下标 i 的最小花费。由于可以选择 0 或者 1 作为初始阶梯,因此有 dp[0] = dp[1] = 0

  4. 2 <= i <= n 时,可以从下标 i-1 使用 cost[i-1] 的花费达到下标 i, 或者从下标 i -2 使用的花费到达下标 i。为了使总花费最小, dp[i] 应该取上述两项的最小值,因此状态转移方程如下:

dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i -2])

依次计算 dp 中的每一项的值,最终得到的 dp[n] 即为达到楼层顶部的最小花费。

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        int[] dp = new int[n + 1];
        dp[0] = dp[1] = 0;
        for (int i=2; i <=n; i++) {
            dp[i] = Math.min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);
        }
        return dp[n];
    }
}

上述的代码时间复杂读度和空间复杂度都是 O(n)。注意当 i>= 的时候,只与 dp[i -1]dp[i-2] 有关,因此可以使用滚动数组的思想优化空间复杂度到 O(1).具体代码如解题代码所示。

复杂度分析

  • 时间复杂度:O(N)
  • 空间复杂度:O(1)

解题代码

题解代码如下(代码中有详细的注释说明):

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        // dp[0], dp[1]
        int prev = 0, curr = 0;
        for (int i=2; i<= n; i++) {
            int next = Math.min(curr + cost[i-1], prev + cost[i-2]);
            prev = curr;
            curr = next;
        }
        return curr;
    }
}

提交后反馈结果:

image.png

参考信息