Easy
题目描述
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
提示:
1 <= n <= 45
解题思路
这是一道经典的动态规划问题,实际上就是斐波那契数列的变形。
核心思路: 要到达第 n 阶楼梯,只能从第 n-1 阶爬 1 步,或从第 n-2 阶爬 2 步。因此状态转移方程为:f(n) = f(n-1) + f(n-2)
解法分析:
递归解法(不推荐): 直接按照递推关系实现,但会有大量重复计算,时间复杂度 O(2^n)
记忆化递归: 使用哈希表缓存已计算结果,避免重复计算,时间复杂度 O(n)
动态规划(推荐): 使用数组存储中间结果,自底向上计算,时间复杂度 O(n),空间复杂度 O(n)
空间优化的动态规划(最优): 由于只需要前两个状态,可以用两个变量代替数组,将空间复杂度优化到 O(1)
边界条件: f(1) = 1(只有一种方法),f(2) = 2(两种方法:1+1 或 2)
下面给出空间优化的动态规划解法,这是最优解。
代码实现
class Solution {
public:
int climbStairs(int n) {
if (n <= 2) return n;
int prev2 = 1, prev1 = 2;
for (int i = 3; i <= n; i++) {
int curr = prev1 + prev2;
prev2 = prev1;
prev1 = curr;
}
return prev1;
}
};
class Solution:
def climbStairs(self, n: int) -> int:
if n <= 2:
return n
prev2, prev1 = 1, 2
for i in range(3, n + 1):
curr = prev1 + prev2
prev2, prev1 = prev1, curr
return prev1
public class Solution {
public int ClimbStairs(int n) {
if (n <= 2) return n;
int prev2 = 1, prev1 = 2;
for (int i = 3; i <= n; i++) {
int curr = prev1 + prev2;
prev2 = prev1;
prev1 = curr;
}
return prev1;
}
}
var climbStairs = function(n) {
if (n <= 2) return n;
let prev2 = 1, prev1 = 2;
for (let i = 3; i <= n; i++) {
const curr = prev1 + prev2;
prev2 = prev1;
prev1 = curr;
}
return prev1;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要计算从 3 到 n 的所有值 |
| 空间复杂度 | O(1) | 只使用常数个额外变量 |
相关题目
. Min Cost Climbing Stairs (Easy)
. Fibonacci Number (Easy)
. N-th Tribonacci Number (Easy)
. Number of Ways to Reach a Position After Exactly k Steps (Medium)
. Count Ways To Build Good Strings (Medium)
. Frog Jump II (Medium)
. The Number of Ways to Make the Sum (Medium)