有限制的楼梯攀登问题解析
问题描述
小U面临一个特殊的楼梯攀登挑战:
- 每次可以选择走1步或2步
- 不能连续走2步
- 需要计算从底部到顶端的所有可能走法
- 给定楼梯层数n,计算总共有多少种不同的走法
解题思路
- 动态规划分析
- 定义状态:dp[i][j] 表示爬到第i层,上一步走了j步的方案数
- 状态转移:根据上一步的步数决定当前可以走的步数
- 最终结果:dp[n][1] + dp[n][2]
- 状态转移规则
-
如果上一步走了1步,当前可以走1步或2步
-
如果上一步走了2步,当前只能走1步
-
状态转移方程:
- dp[i][1] = dp[i-1][1] + dp[i-1][2]
- dp[i][2] = dp[i-2][1]
代码实现
def climb_stairs(n: int) -> int:
# 处理特殊情况
if n <= 1:
return 1
if n == 2:
return 2
# 创建动态规划数组
dp = [[0] * 3 for _ in range(n + 1)]
# 初始化基础状态
dp[1][1] = 1 # 第1层走1步
dp[2][1] = 1 # 第2层走两个1步
dp[2][2] = 1 # 第2层走一个2步
# 状态转移
for i in range(3, n + 1):
dp[i][1] = dp[i-1][1] + dp[i-1][2] # 当前走1步
dp[i][2] = dp[i-2][1] # 当前走2步
return dp[n][1] + dp[n][2]
代码解析
- 特殊情况处理
- n≤1时直接返回1
- n=2时直接返回2
- 动态规划数组
- 使用二维数组dp[i][j]存储状态
- i代表当前层数
- j代表最后一步的步数(1或2)
- 状态转移过程
- 遍历每一层计算可能的方案数
- 分别处理走1步和走2步的情况
优化版本
def climb_stairs_optimized(n: int) -> int:
if n <= 1:
return 1
if n == 2:
return 2
# 只记录前两层状态
one_step = [1, 1] # [走1步, 走2步]
two_steps = [1, 0] # [走1步, 走2步]
for i in range(3, n + 1):
current = [0, 0]
current[0] = one_step[0] + one_step[1] # 走1步
current[1] = two_steps[0] # 走2步
two_steps = one_step
one_step = current
return one_step[0] + one_step[1]
时间复杂度分析
- 时间复杂度
- 基础版本:O(n),需要遍历n个状态
- 优化版本:O(n),循环次数不变
- 空间复杂度
- 基础版本:O(n),需要二维数组存储所有状态
- 优化版本:O(1),只需要常数空间存储状态