第124题 有限制的攀登楼梯

62 阅读3分钟

问题描述

小U最近决定挑战一座非常高的楼梯,每次他可以选择走一步或两步,但有一个重要的限制:他不能连续走两步。因此,小U想知道他总共有多少种不同的方式可以从楼梯的底部走到顶端。

你需要帮他计算在给定的楼梯层数下,小U有多少种走法。


问题分析

  1. 楼梯的步数规则:

    • 每次可以选择走 1 步2 步
    • 但不能连续走两步,即不能连续两次选择走 2 步
  2. 目标:

    • 计算总共有多少种不同的走法,从第 0 层走到第 nn 层。
  3. 解题思路:

    • 如果没有限制,问题的解决方式类似于斐波那契数列。
    • 但是加入了「不能连续两步」的限制后,需要设计新的状态转移方程来满足条件。

解题步骤

1. 定义状态

f(n)f(n) 表示小U到达第 nn 层的方法数。

为了处理「不能连续走两步」的限制,我们可以扩展状态,定义:

  • f(n,1)f(n,1):到达第 nn 层,且最后一步走了 1 步 的方案数。
  • f(n,2)f(n,2):到达第 nn 层,且最后一步走了 2 步 的方案数。

这样,总的方案数为:

f(n)=f(n,1)+f(n,2)f(n) = f(n, 1) + f(n, 2)

2. 状态转移方程

  • 如果最后一步是 1 步,则前一步可以是 11 步或 22 步: f(n,1)=f(n1,1)+f(n1,2)f(n, 1) = f(n-1, 1) + f(n-1, 2)
  • 如果最后一步是 2 步,则前一步必须是 11 步(因为不能连续两步): f(n,2)=f(n2,1)f(n,2)=f(n−2,1)

3. 边界条件

  • f(1,1)=1f(1, 1) = 1:到达第 1 层且最后一步走了 1 步,只有一种方法。
  • f(1,2)=0f(1, 2) = 0:到达第 1 层不可能以 2 步结束。
  • f(2,1)=1f(2, 1) = 1:到达第 2 层且最后一步走了 1 步,只有一种方法(1+1)。
  • f(2,2)=1f(2, 2) = 1:到达第 2 层且最后一步走了 2 步,只有一种方法(直接走 2 步)。

算法实现

我们可以直接用动态规划来实现上述状态转移。

Python代码实现

def count_ways(n):
    if n == 1:
        return 1  # 只有一种方法
    if n == 2:
        return 2  # 两种方法
    
    # 初始化 DP 数组
    f1, f2 = 1, 0  # 表示 f(n-1, 1) 和 f(n-1, 2)
    f3, f4 = 1, 1  # 表示 f(n, 1) 和 f(n, 2)
    
    # 动态规划计算每一层的方式数
    for i in range(3, n + 1):
        new_f1 = f3  # f(n, 1) = f(n-1, 1) + f(n-1, 2)
        new_f2 = f1  # f(n, 2) = f(n-2, 1)
        f1, f2 = f3, f4  # 更新 f(n-1, 1) 和 f(n-1, 2)
        f3, f4 = new_f1 + f2, new_f2  # 更新 f(n, 1) 和 f(n, 2)
    
    return f3 + f4  # 返回总方案数 f(n) = f(n, 1) + f(n, 2)

复杂度分析

  1. 时间复杂度: O(n)O(n)

    • 由于每一层的计算只依赖于前两层,所以算法只需要一次循环即可完成。
  2. 空间复杂度: O(1)O(1)

    • 只需要维护有限的变量来存储当前状态,无需额外数组。

样例分析

样例 1:n = 2

  • 走法:1+1,2
  • 结果:2 种走法。

样例 2:n = 3

  • 走法:1+1+1,1+2,2+1
  • 结果:3 种走法。

样例 3:n = 4

  • 走法:1+1+1+1,1+2+1,2+1+1,1+1+2
  • 结果:4 种走法。

总结

本题通过动态规划的状态设计解决了「不能连续走两步」的限制,核心在于分解状态,并通过简单的递推公式高效计算每一层的方案数。