假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
首先我们将简单的前几种情形进行列举
n | 爬法 | 总数 |
---|---|---|
1 | 1 | 1 |
2 | 1 +1 、2 | 2 |
3 | 1 + 1 + 1、1 + 2、2 + 1 | 3 |
4 | 1 + 1 + 1 + 1、1 + 1 + 2、2 + 2、1 + 2 + 1、2 + 1 + 1 | 5 |
… | … | … |
从表格中可以很明显的看出它满足斐波那契数列的性质 F ( n ) = F ( n − 1 ) + F ( n − 2 ) F(n) = F(n-1) + F(n-2) F(n)=F(n−1)+F(n−2),因此可以使用斐波那契数列的公式进行求解。
class Solution:
def climbStairs(self, n: int) -> int:
if n == 0: return 0
if n == 1: return 1
if n == 2: return 2
p, q = 1, 2
for i in range(2, n):
temp = p + q
p = q
q = temp
return q
斐波那契数列的做法需要我们有一定的经验,以及列举一些简单的情形来判断是否满足。此外,从斐波那契数列的做法中也可以看出,该问题可以被分解为最优子结构的子问题,即最优解可以从其子问题的最优解有效构建,所以可以采用动态规划的方法求解。
第 i i i阶台阶可以看成是第 i − 1 i-1 i−1阶再爬一阶、第 i − 2 i-2 i−2阶再爬两阶,即第 i i i阶的爬法总数是第 i − 1 i-1 i−1阶和第 i − 2 i-2 i−2阶总数的和,所以可以得到动态转移方程: d p [ i ] = d p [ i − 1 ] + d p [ i − 2 ] dp[i] = dp[i-1]+dp[i-2] dp[i]=dp[i−1]+dp[i−2]
class Solution:
def climbStairs(self, n: int) -> int:
if n == 0: return 0
if n == 1: return 1
if n == 2: return 2
dp = [1, 2]
for i in range(2, n):
dp.append(dp[i -1 ] + dp[i - 2])
return dp[-1]