在算法面试中,算法题:爬楼梯(LeetCode 70)是考察动态规划思想的经典入门题。作为一道简单难度的题目,它要求计算爬上n阶楼梯的不同方法数(每次可爬1或2阶),其核心价值在于:通过看似简单的问题,完美诠释了“重叠子问题”与“最优子结构”的动态规划核心思想,同时展现了从暴力递归到空间优化的完整优化路径。掌握这道题的多种解法,能帮助开发者建立算法优化思维,为解决复杂动态规划问题奠定基础。本文将从题目分析、解法演进、代码实现到面试考点,全面拆解这道题的解题思路,结合鳄鱼java技术团队的实测数据,帮你在面试中展现算法深度,正如鳄鱼java在《动态规划入门与实战》中强调的:“爬楼梯问题是动态规划的‘敲门砖’,理解它的优化过程,就能掌握动态规划的核心要义。”
题目深度剖析:从问题定义到数学本质

要解决爬楼梯问题,需先明确问题边界与数学规律,避免陷入“暴力枚举”的低效陷阱。
1. 题目定义与核心约束
题目描述:假设你正在爬楼梯。需要n阶你才能到达楼顶。每次你可以爬1或2个台阶。你有多少种不同的方法可以爬到楼顶?
示例:
- 输入:n = 2 → 输出:2(解释:1阶+1阶,2阶)
- 输入:n = 3 → 输出:3(解释:1+1+1,1+2,2+1)
核心约束:
- n 为正整数(1 ≤ n ≤ 45,LeetCode测试用例上限)
- 每次只能爬1或2阶,无其他步长选择
- 需返回方法数,而非具体路径
2. 数学规律:斐波那契数列的隐藏本质
通过枚举前几阶的方法数,可发现隐藏的数学规律:
- n=1 → 1种方法([1])
- n=2 → 2种方法([1+1, 2])
- n=3 → 3种方法([1+1+1, 1+2, 2+1])
- n=4 → 5种方法([1+1+1+1, 1+1+2, 1+2+1, 2+1+1, 2+2])
观察可知:从n=3开始,方法数等于前两阶方法数之和,即 f(n) = f(n-1) + f(n-2),这正是斐波那契数列的递推公式(区别在于斐波那契数列通常以f(0)=0, f(1)=1开始,而本题f(1)=1, f(2)=2)。
鳄鱼java技术团队提示:识别问题与斐波那契数列的关联,是实现高效解法的关键。
解法一:暴力递归——直观但低效的基础方案
基于递推公式 f(n) = f(n-1) + f(n-2),最直观的解法是递归,但存在严重的性能问题。
1. 算法思路与代码实现
思路:直接翻译递推公式,将f(n)拆解为f(n-1)和f(n-2)的和,递归终止条件为n=1返回1,n=2返回2。
Java代码:
public int climbStairs(int n) {
if (n == 1) return 1;
if (n == 2) return 2;
return climbStairs(n-1) + climbStairs(n-2);
}
2. 复杂度分析与性能瓶颈
- 时间复杂度:O(2ⁿ),递归树呈指数级增长,n=45时需计算约10亿次(2⁴⁵≈3.5×10¹³)。
- 空间复杂度:O(n),递归栈深度为n。
- 性能瓶颈:存在大量重复计算(如f(5)需计算f(4)和f(3),f(4)又需计算f(3)和f(2),f(3)被重复计算)。
鳄鱼java技术团队实测:递归解法在n=30时耗时约0.1秒,n=40时耗时约10秒,n=45时超过1分钟,远无法满足LeetCode的时间要求。
解法二:记忆化递归——缓存优化重叠子问题
通过缓存已计算的子问题结果,避免重复计算,将时间复杂度从指数级降至线性级。
1. 算法思路与代码实现
思路:使用哈希表或数组存储已计算的f(k),递归时先检查缓存,若存在直接返回,否则计算后存入缓存。
Java代码(哈希表缓存):
public int climbStairs(int n) {
Map memo = new HashMap<>();
return dfs(n, memo);
}
private int dfs(int n, Map<Integer, Integer> memo) {
if (n == 1) return 1;
if (n == 2) return 2;
if (memo.containsKey(n)) return memo.get(n);
int res = dfs(n-1, memo) + dfs(n-2, memo);
memo.put(n, res);
return res;
}
优化版(数组缓存):
public int climbStairs(int n) {
int[] memo = new int[n+1];
return dfs(n, memo);
}
private int dfs(int n, int[] memo) {
if (n == 1) return 1;
if (n == 2) return 2;
if (memo[n] != 0) return memo[n];
memo[n] = dfs(n-1, memo) + dfs(n-2, memo);
return memo[n];
}
2. 复杂度分析与性能提升
- 时间复杂度:O(n),每个子问题仅计算一次,共n个问题。
- 空间复杂度:O(n),缓存数组/哈希表占用O(n)空间,递归栈深度O(n)。
- 性能提升:鳄鱼java技术团队实测,n=45时耗时仅0.01ms,性能提升约10⁶倍。
解法三:动态规划——自底向上的迭代优化
动态规划(DP)通过迭代方式自底向上计算,避免递归栈开销,进一步优化性能。
1. 状态定义与转移方程
状态定义:dp[i] 表示爬上i阶楼梯的方法数。
转移方程:dp[i] = dp[i-1] + dp[i-2](第i阶可从i-1阶爬1步,或i-2阶爬2步)。
初始状态:dp[1] = 1,dp[2] = 2。
2. 代码实现与空间优化
基础版(DP数组):
public int climbStairs(int n) { 版权声明
本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。





