「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」
746. 使用最小花费爬楼梯
数组的每个下标作为一个阶梯,第 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]
。
思路:
- 计算出到达每一个台阶时,最小的花费是多少, 存储在数组
dp
中; - 想到达第
i
格台阶, 就需要从i - 1
或者i - 2
处出发; - 所以我们只需要对
Math.min(dp[i-1], dp[i-2])
进行求解; - 我们只需要保证每一次我们走的都是最优解,那么结果必然是最优的;
- 最终对到达终点
n
的求解就是Math.min(dp[n-1], dp[n-2])
。
实现:
/**
* @param {number[]} cost
* @return {number}
*/
var minCostClimbingStairs = function(cost) {
let n = cost.length;
let dp = new Array(n).fill(0);
dp[0] = cost[0];
dp[1] = cost[1];
for (let i = 2; i < n; i++) {
dp[i] = Math.min(dp[i - 2], dp[i - 1]) + cost[i];
}
return Math.min(dp[n - 1], dp[n - 2]);
};
优化
实际上我们并不需要记录所有的结果,只需要保存上一步和上上步的结果即可,所以可以对内存空间做出如下优化:
- 取消用
dp
来存储所有步数的最优解; - 新增变量
prev1
、prev2
来保存上一步和上上步的值; - 最终我们只需要比较走到第n步的
Math.min(prev1, prev2)
即可。
优化代码
/**
* @param {number[]} cost
* @return {number}
*/
var minCostClimbingStairs = function(cost) {
let n = cost.length;
let prev1 = cost[0], prev2 = cost[1];
for (let i = 2; i < n; i++) {
let cur = Math.min(prev1, prev2) + cost[i];
prev1 = prev2;
prev2 = cur;
}
return Math.min(prev1, prev2);
};
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。