746、使用最小花费爬楼梯

  1. 题目
  2. 示例 1:
  3. 示例 2:
    1. 提示:
  4. 题解
    1. 思路1 贪婪 模拟 (自下而上)
    2. 动态规划 (自上而下推倒,自下而上实现)

题目

给你一个整数数组 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 贪婪 模拟 (自下而上)

  • 能走两步,绝不走一部
  • 能省点钱就省点钱
class Solution {
    public int minCostClimbingStairs(int[] cost) {
        // 模拟爬楼梯,取最小值
        int index = -1;
        int costSum = 0;
        while(index < cost.length - 2) {
            // 走一步比走两步的代价小,且走两步之后还要走
            // 如果走一步,至少还得走一步 需要判断两步代价之和
            // 如果走一步,可以不走了
            if (cost[index + 1] == 0 || cost[index + 1] < cost[index + 2] && ((index + 3  == cost.length) || (index + 3 < cost.length && cost[index + 1] + cost[index + 3] <= cost[index + 2]))) {
                costSum += cost[index + 1];
                // System.out.println("cost[index + 1] = "+ cost[index + 1]);
                index += 1;
            } else { // 代价一样,肯定走两步
                costSum += cost[index + 2];
                // System.out.println("cost[index + 2] = "+ cost[index + 2]);
                index += 2;
            }
        }
        return costSum;
    }
}
/**
 *  bad case [0, 1, 2, 2, 2] 解决方案:看见 0 花费,必须白票
 *  bad case [1,2,2,2] 这个不行了,策略有冲突,单调递增和非单调的冲突
 *  缺乏全局视野
 * **/

动态规划 (自上而下推倒,自下而上实现)

定义$dp[i]$ 为到达i位置的最小花费,两种情况:

  • 从 $i-1$ 到达 $dp[i] = dp[i-1] + cost[i-1]$
  • 从 $i - 2$ 到达 $dp[i] = dp[i-2] + cost[i-2]$

两者取最小,则状态递推公式:

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

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

// 优化空间复杂度
class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int cur = 0,pre = 0;
        for (int i = 2;i <= cost.length;i++) {
            int next = Math.min(cur+cost[i-1],pre + cost[i-2]);
            pre = cur;
            cur = next;
        }
        return cur;
    }
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

💰

Title:746、使用最小花费爬楼梯

Count:763

Author:攀登

Created At:2024-06-04, 11:17:24

Updated At:2024-06-15, 15:52:32

Url:http://jiafeimao-gjf.github.io/2024/06/04/746%E3%80%81%E4%BD%BF%E7%94%A8%E6%9C%80%E5%B0%8F%E8%8A%B1%E8%B4%B9%E7%88%AC%E6%A5%BC%E6%A2%AF/

Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

×

Help us with donation