LeetCode-70-爬楼梯

1 问题描述

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。

2 示例

示例1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1: 1 阶 + 1 阶
2: 2 阶

示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1: 1 阶 + 1 阶 + 1 阶
2: 1 阶 + 2 阶
3: 2 阶 + 1 阶

3 解法

3.1 暴力破解

  • 采用递归的方法:将会把所有可能爬的阶数进行组合,也就是1122。而在每一步中我们都会继续调用climbStairsclimbStairs这个函数模拟爬11阶和22阶的情形,并返回两个函数的返回值之和。

climbStairs(i,n)=(i+1,n)+climbStairs(i+2,n)climbStairs(i, n)=(i+1, n)+climbStairs(i+2, n)

其中ii定义了当前阶数,而nn定义了目标阶数。

  • n=5n=5时,递归树是这样的:

  • Python3实现:

n = 3
def solution(n):
return climbStairs(0, n)

def climbStairs(i, n):
if i > n:
return 0
elif i == n:
return 1
else:
return climbStairs(i+1, n) + climbStairs(i+2, n)

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

3.2 记忆化递归

  • 在上一种方法中,我们计算每一步的结果时出现了冗余,观察上图的递归树可以看出,(4,5)(4,5)在树中出现了许多次,而用memo[4]memo[4]可以直接记忆i=4i=4时的方法数。因此我们可以把每一步的结果存储在memomemo数组之中,每当函数再次被调用,我们就直接从memomemo数组返回结果。

  • memomemo数组的帮助下,我们得到了一个修复的递归树,其大小减少到nn

  • Python3实现:

n = 3
def solution(n):
memo = [0]*n
return climbStairs(0, n, memo)

def climbStairs(i, n, memo):
if i > n:
return 0
elif i == n:
return 1
elif memo[i] > 0:
return memo[i]
else:
memo[i] = climbStairs(i+1, n, memo) + climbStairs(i+2, n, memo)
return memo[i]

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

3.3 动态规划法

  • 不难发现,这个问题可以被分解为一些包含最优子结构的子问题,即它的最优解可以从其子问题的最优解来有效地构建,我们可以使用动态规划来解决这一问题。

  • ii阶可以由以下两种方法得到:

    • 在第(i1)(i-1)阶后向上爬11阶。
    • 在第(i2)(i-2)阶后向上爬22阶。
  • 所以到达第ii阶的方法总数就是到第(i1)(i−1)阶和第(i2)(i−2)阶的方法数之和。

  • dp[i]dp[i]表示能到达第ii阶的方法总数:

dp[i]=dp[i1]+dp[i2]dp[i]=dp[i-1]+dp[i-2]

  • Python3实现:
n = 3

if n==1:
print (1)
elif n==2:
print (2)
else:
pre = 2
ppre = 1
times = n-2
while times:
times -= 1
ans = pre + ppre
ppre = prepre = ans
print (ans)

3.4 斐波那契数列

  • 观察答案序列可知,是一个斐波那契数列,直接套用公式即可,这里不再赘述。
文章作者: Alston
文章链接: https://lizitong67.github.io/2020/02/21/LeetCode-70-%E7%88%AC%E6%A5%BC%E6%A2%AF/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Alston's blog