2026-02-21:爬楼梯Ⅱ。用go语言,你要爬一段共有 n+1 级的台阶,编号从 0 到 n。给定一个长度为 n、下标从 1 开始的数组 costs,其中 costs[i] 表示第 i 级台阶自身的费用(第 0 级没有对应的 costs 项)。
每一步可以从当前台阶 i 向前跳到 i+1、i+2 或 i+3 中的任一台阶,若从 i 跳到 j,则这次移动会增加 costs[j] 与跳跃距离的平方之和作为代价,即增加 costs[j] + (j − i)^2。初始位于台阶 0,累计费用从 0 开始。
返回到达台阶 n 时可能得到的最小累计费用。
1 <= n == costs.length <= 100000。
1 <= costs[i] <= 10000。
输入:n = 4, costs = [1,2,3,4]。
输出:13。
解释:
一个最优路径是 0 → 1 → 2 → 4。
| 跳跃 | 成本计算 | 成本 |
|---|---|---|
| 0 → 1 | costs[1] + (1 - 0)^2 = 1 + 1 | 2 |
| 1 → 2 | costs[2] + (2 - 1)^2 = 2 + 1 | 3 |
| 2 → 4 | costs[4] + (4 - 2)^2 = 4 + 4 | 8 |
因此,最小总成本为 2 + 3 + 8 = 13。
题目来自力扣3693。
问题理解
- 有
n+1级台阶,编号0到n。 - 数组
costs长度是n,下标从1开始,costs[i]表示第i级台阶的费用。 - 第
0级没有费用。 - 从台阶
i可以跳到i+1、i+2或i+3。 - 从
i跳到j的成本 =costs[j] + (j - i)^2。 - 从
0出发,累计费用初始为0。 - 要到达台阶
n,求最小累计费用。
例子说明
题目给的例子:
n = 4,costs = [1,2,3,4]。- 路径:
0 → 1 → 2 → 40 → 1:costs[1] + 1² = 1 + 1 = 21 → 2:costs[2] + 1² = 2 + 1 = 32 → 4:costs[4] + 2² = 4 + 4 = 8
- 总成本 =
2 + 3 + 8 = 13
代码逻辑分析(逐步推理)
1. 初始化
- 设
f0表示到达台阶0的最小费用,即f0 = 0。 - 如果
n == 0,直接返回f0。
2. 到达台阶 1
- 从
0到1只有一种跳法(距离 1)。 - 成本 =
costs[1] + 1(因为(1-0)² = 1)。 - 所以
f1 = costs[0] + 1 + f0。 - 如果
n == 1,返回f1。
3. 到达台阶 2
有两种可能:
- 从
0直接跳到2(距离 2):- 成本 =
costs[2] + 4 + f0
- 成本 =
- 从
1跳到2(距离 1):- 成本 =
costs[2] + 1 + f1
- 成本 =
代码中比较这两者,取最小值:
if costs[1] + f1 + 1 < costs[1] + f0 + 4:
f2 = costs[1] + f1 + 1
else:
f2 = costs[1] + f0 + 4
注意这里 costs[1] 是 costs[2](因为下标从 1 开始),所以这其实是:
costs[2] + f1 + 1(从 1 跳过来)costs[2] + f0 + 4(从 0 跳过来)
4. 到达台阶 i ≥ 3
从 i-3、i-2、i-1 都可以跳到 i:
- 从
i-3跳过来:距离 3,成本 =f(i-3) + costs[i] + 9 - 从
i-2跳过来:距离 2,成本 =f(i-2) + costs[i] + 4 - 从
i-1跳过来:距离 1,成本 =f(i-1) + costs[i] + 1
取三者最小值:
f = min(f0 + 9 + costs[i-1], f1 + 4 + costs[i-1], f2 + 1 + costs[i-1])
这里的 f0 其实是 f(i-3),f1 是 f(i-2),f2 是 f(i-1)。
更新 f0、f1、f2 为下一轮的状态。
算法流程总结
- 如果
n == 0,直接返回 0。 - 如果
n == 1,返回costs[1] + 1。 - 如果
n == 2,返回min(costs[2] + f1 + 1, costs[2] + f0 + 4)。 - 从
i = 3到n:- 计算到达
i的最小费用:- 从
i-3来:f0 + 9 + costs[i-1] - 从
i-2来:f1 + 4 + costs[i-1] - 从
i-1来:f2 + 1 + costs[i-1]
- 从
- 取最小值作为
f。 - 更新
f0 = f1、f1 = f2、f2 = f。
- 计算到达
- 返回
f2,即到达台阶n的最小费用。
时间复杂度和空间复杂度
- 时间复杂度:我们只遍历了从
i=0到n一次,每一步做常数次比较和计算,所以是 O(n)。 - 额外空间复杂度:只用了三个变量
f0、f1、f2来记录状态,没有用数组存储所有结果,所以是 O(1)。
最终答案:
- 时间复杂度:O(n)
- 额外空间复杂度:O(1)
Go完整代码如下:
package main
import (
"fmt"
)
func minNew(a, b, c int) int {
if a <= b && a <= c {
return a
} else if b <= a && b <= c {
return b
}
return c
}
func climbStairs(n int, costs []int) int {
var f0, f1, f2 int
f0 = 0
if n == 0 {
return f0
}
f1 = costs[0] + 1 + f0
if n == 1 {
return f1
}
// min(costs[1] + f1 + 1, costs[1] + f0 + 4)
if costs[1]+f1+1 < costs[1]+f0+4 {
f2 = costs[1] + f1 + 1
} else {
f2 = costs[1] + f0 + 4
}
if n == 2 {
return f2
}
for i := 3; i <= n; i++ {
f := minNew(f0+9+costs[i-1], f1+4+costs[i-1], f2+1+costs[i-1])
f0 = f1
f1 = f2
f2 = f
}
return f2
}
func main() {
n := 4
costs := []int{1, 2, 3, 4}
result := climbStairs(n, costs)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
def min_new(a, b, c):
if a <= b and a <= c:
return a
elif b <= a and b <= c:
return b
return c
def climbStairs(n, costs):
f0 = 0
if n == 0:
return f0
f1 = costs[0] + 1 + f0
if n == 1:
return f1
# min(costs[1] + f1 + 1, costs[1] + f0 + 4)
if costs[1] + f1 + 1 < costs[1] + f0 + 4:
f2 = costs[1] + f1 + 1
else:
f2 = costs[1] + f0 + 4
if n == 2:
return f2
for i in range(3, n + 1):
f = min_new(f0 + 9 + costs[i - 1],
f1 + 4 + costs[i - 1],
f2 + 1 + costs[i - 1])
f0 = f1
f1 = f2
f2 = f
return f2
def main():
n = 4
costs = [1, 2, 3, 4]
result = climbStairs(n, costs)
print(result)
if __name__ == "__main__":
main()
C++完整代码如下:
#include <iostream>
#include <vector>
using namespace std;
int min_new(int a, int b, int c) {
if (a <= b && a <= c) {
return a;
} else if (b <= a && b <= c) {
return b;
}
return c;
}
int climbStairs(int n, vector<int>& costs) {
int f0, f1, f2;
f0 = 0;
if (n == 0) {
return f0;
}
f1 = costs[0] + 1 + f0;
if (n == 1) {
return f1;
}
// min(costs[1] + f1 + 1, costs[1] + f0 + 4)
if (costs[1] + f1 + 1 < costs[1] + f0 + 4) {
f2 = costs[1] + f1 + 1;
} else {
f2 = costs[1] + f0 + 4;
}
if (n == 2) {
return f2;
}
for (int i = 3; i <= n; i++) {
int f = min_new(f0 + 9 + costs[i - 1],
f1 + 4 + costs[i - 1],
f2 + 1 + costs[i - 1]);
f0 = f1;
f1 = f2;
f2 = f;
}
return f2;
}
int main() {
int n = 4;
vector<int> costs = {1, 2, 3, 4};
int result = climbStairs(n, costs);
cout << result << endl;
return 0;
}