🧠 引言
“爬楼梯问题”堪称算法界的“Hello World”:
一次可以爬 1 级或 2 级楼梯,问爬到第
n层有多少种不同的方法?
这道题表面简单,但它却是递归、动态规划与性能优化的完美训练场。
本篇我们将通过 递归 + 迭代 + 记忆化 三种方式,分别用 JavaScript 和 Python 编写,并对比它们的执行效率与易错点。
📌 一、问题定义
输入:n = 5
输出:8
解释:
1-1-1-1-1
1-1-1-2
1-1-2-1
1-2-1-1
2-1-1-1
2-2-1
2-1-2
1-2-2
这是一个 斐波那契型问题:
f(n) = f(n - 1) + f(n - 2)
🧱 二、递归解法(暴力)
✅ JavaScript
function climbStairs(n) {
if (n <= 2) return n;
return climbStairs(n - 1) + climbStairs(n - 2);
}
console.log(climbStairs(5)); // 输出 8
✅ Python
def climb_stairs(n):
if n <= 2:
return n
return climb_stairs(n - 1) + climb_stairs(n - 2)
print(climb_stairs(5)) # 输出 8
⛔ 缺点:时间复杂度为 O(2^n),指数级爆炸!
⚡ 三、记忆化递归优化(Top-down)
✅ JavaScript
function climbStairsMemo(n, memo = {}) {
if (n <= 2) return n;
if (memo[n]) return memo[n];
memo[n] = climbStairsMemo(n - 1, memo) + climbStairsMemo(n - 2, memo);
return memo[n];
}
console.log(climbStairsMemo(35)); // 快速输出 14930352
✅ Python
def climb_stairs_memo(n, memo={}):
if n <= 2:
return n
if n in memo:
return memo[n]
memo[n] = climb_stairs_memo(n - 1, memo) + climb_stairs_memo(n - 2, memo)
return memo[n]
print(climb_stairs_memo(35)) # 快速输出 14930352
✅ 时间复杂度优化到 O(n),空间也只用 O(n)
🚀 四、迭代解法(Bottom-up)
✅ JavaScript
function climbStairsIter(n) {
if (n <= 2) return n;
let first = 1, second = 2;
for (let i = 3; i <= n; i++) {
[first, second] = [second, first + second];
}
return second;
}
console.log(climbStairsIter(35)); // 输出 14930352
✅ Python
def climb_stairs_iter(n):
if n <= 2:
return n
first, second = 1, 2
for _ in range(3, n + 1):
first, second = second, first + second
return second
print(climb_stairs_iter(35)) # 输出 14930352
✅ 时间复杂度:O(n)
✅ 空间复杂度:O(1) → 最优解
🧪 五、三种解法性能对比
| 解法方式 | 时间复杂度 | 空间复杂度 | 是否推荐 | 备注 |
|---|---|---|---|---|
| 普通递归 | O(2^n) | O(n) | ❌ | 超时严重,仅适合教学 |
| 记忆化递归 | O(n) | O(n) | ✅ | 简洁、易理解 |
| 迭代(滚动数组) | O(n) | O(1) | ✅✅ | 企业级标准写法 |
⚠️ 六、常见错误提醒
| 问题 | 正确写法 |
|---|---|
| 忘记终止条件 | if (n <= 2) return n |
| Python memo 默认参数陷阱 | 函数外定义 memo,或用 @lru_cache |
| 忘记返回缓存结果 | return memo[n] |
🧩 七、拓展任务
- 支持“每次可以跳 1、2、3级”的爬楼梯变种
- 用
@lru_cache写递归版本(Python) - 用尾递归优化(语言支持的情况下)
📚 总结一句话
在性能面前,递归和迭代都不是死敌,而是你算法思维灵活度的体现!
下一篇预告:
📘 第10篇:【用栈解决括号匹配问题】JS 与 Python 解锁面试常客题!