LeetCode 热题 100 70. 爬楼梯
LeetCode 热题 100 | 70. 爬楼梯
大家好,今天我们来解决一道经典的动态规划入门题——爬楼梯。这道题在LeetCode上被标记为简单难度,要求我们计算爬到第n阶楼梯的不同方法数,每次可以爬1或2个台阶。下面我将详细讲解解题思路,并附上Python代码实现。
问题描述
你需要爬一个有n阶的楼梯,每次可以爬1或2个台阶。求有多少种不同的方法可以爬到楼顶。
示例:
- n=2 → 2种 (1+1, 2)
- n=3 → 3种 (1+1+1, 1+2, 2+1)
正确解法一:动态规划(迭代法)
def climbStairs(n):if n <= 2:return ndp = [0]*(n+1)dp[1], dp[2] = 1, 2for i in range(3, n+1):dp[i] = dp[i-1] + dp[i-2]return dp[n]
时间复杂度:O(n)
空间复杂度:O(n)
正确解法二:空间优化动态规划
def climbStairs(n):if n <= 2:return na, b = 1, 2for _ in range(3, n+1):a, b = b, a+breturn b
时间复杂度:O(n)
空间复杂度:O(1)
正确解法三:矩阵快速幂(进阶)
def climbStairs(n):def matrix_pow(mat, power):# 实现矩阵快速幂...mat = [[1,1],[1,0]]return matrix_pow(mat, n)[0][0]
时间复杂度:O(log n)
空间复杂度:O(1)
常见错误解法分析
错误解法:朴素递归
def climbStairs(n):if n == 1:return 1if n == 2:return 2return climbStairs(n-1) + climbStairs(n-2)
问题分析:
- 存在大量重复计算(如计算climbStairs(5)会重复计算climbStairs(3))
- 时间复杂度高达O(2n),n=45时需要约245≈35万亿次计算
- 实际运行会超时(LeetCode上n=45时无法通过)
错误解法可视化(n=5时的调用树):
climbStairs(5)
├── climbStairs(4)
│ ├── climbStairs(3)
│ │ ├── climbStairs(2)
│ │ └── climbStairs(1)
│ └── climbStairs(2)
└── climbStairs(3)├── climbStairs(2)└── climbStairs(1)
改进建议:
- 记忆化递归(添加缓存):
def climbStairs(n, memo={1:1, 2:2}):if n not in memo:memo[n] = climbStairs(n-1) + climbStairs(n-2)return memo[n]
- 改用迭代法(推荐)
性能对比(n=45时)
方法 | 时间复杂度 | 实际运行时间 |
---|---|---|
朴素递归 | O(2^n) | >1小时 |
记忆化递归 | O(n) | 0.1ms |
基础动态规划 | O(n) | 0.05ms |
空间优化动态规划 | O(n) | 0.03ms |
矩阵快速幂 | O(log n) | 0.01ms |
关键总结
- 避免朴素递归:对于有重叠子问题的情况,递归会导致指数级时间复杂度
- 优先选择迭代:动态规划的迭代实现是最可靠的解法
- 空间可以优化:用两个变量代替数组可将空间复杂度降到O(1)
- 注意边界条件:n=1和n=2时需要特殊处理
最终推荐写法:
def climbStairs(n):a, b = 1, 1for _ in range(1, n):a, b = b, a + breturn b