[路飞]_程序员必刷力扣题: 使用最小花费爬楼梯

338 阅读3分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

使用最小花费爬楼梯

力扣链接

数组的每个下标作为一个阶梯,第 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 。

提示:

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

动态规划

思路

很明显这里 我们可以使用动态规划来记录到达每个阶梯所用的最少值

明确规则:

  • 到达某个阶梯不消耗体力,要继续往上走(一步或者两步)则需要消耗当前阶梯对应的体力。
  • 到达阶梯i的可能有两种,从i-1上1个阶梯,或者从i-2上2个阶梯
  • 阶梯0和阶梯1可以直接到达 所以消耗体力dp[0] = dp[1] = 0
  • 本题需要到达阶梯顶,明显要到达dp[cost.length]

明确以上规则后就方便写出代码了,我们首先要声明一个dp数组,切dp[0] = dp[1] = 0

然后从i=2开始循环到i=cost.length,那么dp数组的最后一个值就是到达阶梯顶需要的最少体力

到达i的最少体力就是 到达dp[i-1]+cost[i-1] 对比dp[i-2]+cost[i-2] 去小的值

最后结束后返回dp[cost.length]等价dp[dp.length-1]

var minCostClimbingStairs = function (cost) {
    var dp = []
    dp[0] = dp[1] = 0
    for (var 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]
};

动态规划(滚动数组优化空间复杂度)

思路

上面动态规划中我们用dp数组记录下了每个i的结果,空间负责度为O(n)

  • 每次只需要访问dp[i-1](prev表示)和dp[i-2](curr表示),并且会得到dp[i](res表示),三个值会依次向前滚动,即res的结果同上计算方式,prev = curr,curr = res
  • 这样我们就是省去dp数组,使空间复杂度降低到O[i]
var minCostClimbingStairs = function (cost) {
    var curr = 0;
    var prev = 0
    var res = 0;
    for (var i = 2; i <= cost.length; i++) {
        res = Math.min(curr + cost[i - 1], prev + cost[i - 2])
        prev = curr
        curr = res
    }
    return res
};