📅  最后修改于: 2023-12-03 15:10:02.060000             🧑  作者: Mango
这个问题可以用动态规划来解决。我们可以定义一个数组 dp
,其中 dp[i]
表示到达第 i
级楼梯的方法数。显然,dp[0] = 1
、dp[1] = 1
,因为只有一种方法可以到达第 0 级或第 1 级楼梯(即不跳或者跳一次)。
对于 dp[i]
,我们可以通过 dp[i-1]
和 dp[i-2]
来计算。因为一次跳跃可以跳 1 或 2 个单位,所以到达第 i
级楼梯的方法数量就是到达第 i-1
级楼梯的方法数量加上到达第 i-2
级楼梯的方法数量。也就是说,dp[i] = dp[i-1] + dp[i-2]
。
下面是具体的实现代码:
def print_all_ways_to_nth_stair(n):
dp = [0] * (n + 1)
dp[0] = 1
dp[1] = 1
for i in range(2, n+1):
dp[i] = dp[i-1] + dp[i-2]
ways = []
def backtrack(path, steps):
if steps == n:
ways.append(path)
return
elif steps > n:
return
else:
backtrack(path+[1], steps+1)
backtrack(path+[2], steps+2)
backtrack([], 0)
return ways
这个函数的时间复杂度为 $O(n^2)$,因为需要计算所有的 dp
值。但是这个函数还有一个问题,就是可能会有重复的路径。比如到达第 4 级楼梯,有两种方法:[1, 1, 1, 1]
和 [2, 2]
,但是同样也可以由 [1, 2, 1]
和 [2, 1, 1]
、[1, 1, 2]
组成。所以我们还需要一个递归函数来去重:
def print_all_ways_to_nth_stair(n):
dp = [0] * (n + 1)
dp[0] = 1
dp[1] = 1
for i in range(2, n+1):
dp[i] = dp[i-1] + dp[i-2]
ways = []
def backtrack(path, steps):
if steps == n:
ways.append(path)
return
elif steps > n:
return
else:
if len(path) >= 2 and path[-1] == 2 and path[-2] == 2:
return
backtrack(path+[1], steps+1)
backtrack(path+[2], steps+2)
backtrack([], 0)
return ways
递归函数中的判断语句 if len(path) >= 2 and path[-1] == 2 and path[-2] == 2:
表示如果新的步数是 2,且前面已经有两步也是 2,那么这条路径就是重复的,可以直接返回。这样就可以去重了。
最后,我们可以调用这个函数来打印出所有的到达第 N 级楼梯的方法:
n = 4
ways = print_all_ways_to_nth_stair(n)
for way in ways:
print(way)
输出会是:
[1, 1, 1, 1]
[1, 2, 1]
[2, 1, 1]
[2, 2]