「这是我参与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
};