LeetCode 746. 使用最小花费爬楼梯
题目描述


题意分析
cost[i]是站在第i级台阶后、继续向上走之前需要支付的费用,支付后可以向上走一级或两级。可以直接从第零级或第一级开始,求到达楼顶所需的最少总费用。楼顶是数组之外的第
n个位置,不是最后一个有费用的台阶n - 1。允许跨过未踩到的台阶,因此不必支付所有费用;题目只求最小金额,不需要返回经过的台阶序列。
解法:滚动 DP
核心思路
[!blue]
定义
dp[i]为到达位置i、还没有支付当前位置费用时的最小累计花费。起点可以自由选择第零级或第一级,所以dp[0] = dp[1] = 0;这不表示这两个台阶永远免费,而是它们的费用在离开时才加入。到达位置
i的最后一步只有两个来源:从i - 1走一级,需要dp[i - 1] + cost[i - 1];或者从i - 2走两级,需要dp[i - 2] + cost[i - 2]。这两种情况覆盖所有合法走法,分别使用到达前驱的最小代价后再取较小值,得到当前位置的最优费用。转移只需要前两个状态,可以用
prev2、prev1滚动保存。处理位置i之前,它们分别表示dp[i - 2]和dp[i - 1]。先计算本轮cur,再把旧prev1移到prev2,把cur放到prev1,为下一位置保留正确状态。循环必须计算到
i = n。这一轮支付的是最后两种可能前驱的台阶费用,楼顶本身没有费用,也不会读取不存在的cost[n]。处理完后,prev1就是顶部位置的最小累计花费。
解题步骤
- 初始化
prev2 = 0、prev1 = 0,对应两个可选起点的到达费用。- 从位置
2依次计算到位置n。- 每轮比较
prev1 + cost[i - 1]与prev2 + cost[i - 2],较小值记为cur。- 按顺序执行
prev2 = prev1、prev1 = cur,保留下一轮需要的历史状态。- 返回最终
prev1。
代码实现
class Solution {
// 转移:dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])。
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
int prev2 = 0;
int prev1 = 0;
// 顶部在数组之外的 n 位置,也必须完成这一轮转移
for (int i = 2; i <= n; i++) {
int cur = Math.min(prev1 + cost[i - 1], prev2 + cost[i - 2]);
// 先保存旧前一项,再写入当前结果
prev2 = prev1;
prev1 = cur;
}
return prev1;
}
}
func minCostClimbingStairs(cost []int) int {
// 转移:dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])。
n := len(cost)
prev2, prev1 := 0, 0
// 顶部在数组之外的 n 位置,也必须完成这一轮转移
for i := 2; i <= n; i++ {
cur := prev1 + cost[i-1]
if prev2+cost[i-2] < cur {
cur = prev2 + cost[i-2]
}
// 先保存旧前一项,再写入当前结果
prev2 = prev1
prev1 = cur
}
return prev1
}
复杂度分析
- 时间复杂度:$O(n)$,每个位置做一次常数时间转移。
- 空间复杂度:$O(1)$,只保存前两个位置和当前结果。
关键点总结
[!green]
- 状态把费用记在离开前驱时,初始化和转移都必须与此约定一致。
- 两个起点到达费用为零,选择从哪一级开始已包含在动态规划中。
- 楼顶位置
n需要计算,但不存在cost[n],只支付对应前驱费用。- 先算新值再移动旧值,避免丢失相隔两级的前驱状态。
易错点总结
[!yellow]
- 只计算到
n - 1,得到的是到达最后一个台阶的费用,并未到达顶部。- 初始化第二个起点为第零级费用,会强制经过第零级,遗漏直接从第一级开始的方案。
- 转移时加
cost[i],混淆了状态的支付时机,也会在顶部下标越界。- 先覆盖前一状态再复制给前二状态,会使下一轮读到两份相同的新值。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 70. 爬楼梯 | 简单 | 同样从前一或前两阶转移,原题统计走法,本题取最低费用。 |
| 198. 打家劫舍 | 中等 | 同样是线性DP并能滚动压缩,原题最大化不相邻收益,本题选择走一阶或两阶的最低代价。 |
| 91. 解码方法 | 中等 | 按最后一段长度递推前缀方案数;本题转为达到当前台阶的最小费用,该题最后编码可占一位或两位。 |
| 1137. 第 N 个泰波那契数 | 简单 | 按最后一段长度递推前缀方案数;本题转为达到当前台阶的最小费用,该题依赖前三个状态。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!