刷题(4) | 豆包MarsCode AI刷题

65 阅读3分钟

问题描述

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

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

测试样例

样例1: 输入:n=2 输出:2

样例2: 输入:n=3 输出:3

样例3: 输入:n=4 输出:4

解题思路

为了计算小U的不同走法数目,我们可以将问题转化为动态规划(Dynamic Programming)的问题。动态规划适用于这种通过解决子问题并存储其结果来构建最终解决方案的问题。

关键限制

  • 选择:每次可以选择走一步或两步。
  • 限制:不能连续走两步。

状态定义

为了考虑到“不能连续走两步”的限制,我们需要追踪每一步的走法。因此,我们可以定义以下两个状态:

  1. dp[i][0] :到达第i层,并且最后一步走了一步的走法数。
  2. dp[i][1] :到达第i层,并且最后一步走了两步的走法数。

这样,我们可以根据这两个状态来避免连续走两步的情况。

状态转移方程

根据定义的状态,我们可以建立如下的状态转移方程:

  • 走一步的情况 (dp[i][0])

    • 无论前一步是走了一步还是走了两步,都可以走一步到达当前层。
    • 因此: dp[i][0]=dp[i1][0]+dp[i1][1]dp[i][0]=dp[i−1][0]+dp[i−1][1]
  • 走两步的情况 (dp[i][1])

    • 只有在前一步走了一步的情况下,才能走两步到达当前层。
    • 因此: dp[i][1]=dp[i2][0]dp[i][1]=dp[i−2][0]

初始条件

  • dp[0][0] :在第0层,且没有走任何步(因为起点),只有一种方式,即不动。
dp[0][0]=1dp[0][0]=1
  • dp[0][1] :在第0层,且最后一步走了两步,这是不可能的。
dp[0][1]=0dp[0][1]=0

结果计算

最终,到达第n层的总走法数为:dp[n][0]+dp[n][1]dp[n][0]+dp[n][1]

算法流程

  • 初始化:

    • dp[0][0] = 1,表示在第0层且最后一步不是两步的走法数为1。
    • dp[0][1] = 0,因为不可能在第0层且最后一步是两步。
  • 状态转移:

    • 走一步的情况:

      • 无论前一步是走了一步还是两步,都可以走一步到达当前层。
      • dp[i][0] = dp[i - 1][0] + dp[i - 1][1]
    • 走两步的情况:

      • 只有当前一步走了一步时,才能走两步到达当前层。
      • dp[i][1] = dp[i - 2][0]
  • 结果计算:

    • 总的走法数目为dp[n][0] + dp[n][1]

代码实现

def solution(n):
    if n == 0:
        return 1
    dp = [[0, 0] for _ in range(n + 2)]
    dp[0][0] = 1  # 起始状态

    for i in range(1, n + 1):
        # 最后一步走了一步
        dp[i][0] = dp[i - 1][0] + dp[i - 1][1]
        if i >= 2:
            # 最后一步走了两步,前一步不能是两步
            dp[i][1] = dp[i - 2][0]
    return dp[n][0] + dp[n][1]

if __name__ == "__main__":
    print(solution(2) == 2)  

总结

本题是一个典型的动态规划问题,结合了路径计数和状态约束的特点。关键在于:

  1. 状态定义:明确区分不同的状态,确保约束条件被满足。在本题中,通过区分最后一步走了一步还是两步,有效地避免了连续走两步的情况。
  2. 状态转移方程:根据当前状态与之前的状态之间的关系,建立合理的转移方程。这一步需要仔细分析题目中的限制条件。
  3. 边界条件处理:处理特殊情况,如n=0n=1,以避免数组越界或逻辑错误。

通过系统地分解问题并应用动态规划的方法,能够高效地解决这一问题。