题目分析
这道题要求计算在给定楼梯层数 n 的情况下,小U从底部到达楼梯顶端的不同走法。每次小U可以选择走一步或两步,但是有一个约束条件:小U不能连续走两步。
例如:
-
在
n = 2的情况下,小U可以通过以下两种方式走到顶端:- 走一步,走一步(1, 1)
- 走两步(2)
-
在
n = 3的情况下,小U可以通过以下三种方式走到顶端:- 走一步,走一步,走一步(1, 1, 1)
- 走一步,走两步(1, 2)
- 走两步,走一步(2, 1)
我们需要计算对于任意给定 n,总共有多少种不同的走法。
思路
为了解决这个问题,可以使用 动态规划(Dynamic Programming, DP)。在这个问题中,我们的目标是找出到达楼梯顶部的所有可能的路径数,而动态规划可以帮助我们从底部到顶部逐步推导出解。
关键分析:
-
状态定义: 设
dp[i]表示从底部到达第i层的不同走法数。 -
状态转移:
-
小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层时,最后一步是走两步的情况)
-
-
-
初始条件:
dp[0][0] = 1:表示从底部开始时,最后一步是走一步,走法数为1(即走到第0层)。dp[0][1] = 0:表示不可能直接走两步到达第0层。
-
返回结果: 最终我们需要返回的是
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数组,直到最终问题的解被计算出来。
- 根据状态转移方程,逐步填充整个