有限制的楼梯攀登| 豆包MarsCode AI刷题

54 阅读3分钟

image.png

题目分析

这道题要求计算在给定楼梯层数 n 的情况下,小U从底部到达楼梯顶端的不同走法。每次小U可以选择走一步或两步,但是有一个约束条件:小U不能连续走两步。

例如:

  • n = 2 的情况下,小U可以通过以下两种方式走到顶端:

    1. 走一步,走一步(1, 1)
    2. 走两步(2)
  • n = 3 的情况下,小U可以通过以下三种方式走到顶端:

    1. 走一步,走一步,走一步(1, 1, 1)
    2. 走一步,走两步(1, 2)
    3. 走两步,走一步(2, 1)

我们需要计算对于任意给定 n,总共有多少种不同的走法。

思路

为了解决这个问题,可以使用 动态规划(Dynamic Programming, DP)。在这个问题中,我们的目标是找出到达楼梯顶部的所有可能的路径数,而动态规划可以帮助我们从底部到顶部逐步推导出解。

关键分析:

  1. 状态定义:dp[i] 表示从底部到达第 i 层的不同走法数。

  2. 状态转移:

    • 小U每次只能选择走一步或两步:

      • 如果小U在第 i 层时选择走一步,那么他之前必须在第 i-1 层,而此时他不能连续走两步,因此我们可以得到:

        • dp[i][0] = dp[i-1][0] + dp[i-1][1](到达第 i 层时,最后一步是走一步的情况)
      • 如果小U在第 i 层时选择走两步,那么他之前必须在第 i-2 层,并且此时不能是连续两步,所以我们可以得到:

        • dp[i][1] = dp[i-2][0](到达第 i 层时,最后一步是走两步的情况)
  3. 初始条件:

    • dp[0][0] = 1:表示从底部开始时,最后一步是走一步,走法数为1(即走到第0层)。
    • dp[0][1] = 0:表示不可能直接走两步到达第0层。
  4. 返回结果: 最终我们需要返回的是 dp[n][0] + dp[n][1],即到达第 n 层时,最后一步是走一步或者走两步的所有可能

def solution(n): # 初始化动态规划数组 dp = [[0, 0] for _ in range(n + 1)] # 初始条件 dp[0][0] = 1 # 到达第0层时,最后一步是走一步的走法数为1 dp[0][1] = 0 # 到达第0层时,最后一步是走两步的走法数为0 # 状态转移 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]

时间复杂度分析:

  • 时间复杂度: 每次我们都需要计算一个新的 dp[i][0]dp[i][1],所以总时间复杂度为 O(n),其中 n 是楼梯的层数。
  • 空间复杂度: 我们使用了一个 dp 数组来存储每层楼梯的不同走法数,因此空间复杂度为 O(n)

###动规的一般步骤

  • 定义状态(子问题)

    • 确定子问题的状态,一般会定义一个数组 dp,其中 dp[i] 表示求解到第 i 的最优解。
  • 状态转移方程

    • 通过状态转移方程将一个子问题的解通过已知的子问题的解来得到。也就是说,我们通过推导出每个子问题的解与其他子问题的关系。
  • 初始化

    • 为了便于递推,需要给定一个或多个初始条件。一般来说,初始条件是 dp[0] 或者 dp[1],代表最基础的情况。
  • 求解最终问题

    • 根据状态转移方程,逐步填充整个 dp 数组,直到最终问题的解被计算出来。