爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
3. 1 阶 + 1 阶 + 1 阶
4. 1 阶 + 2 阶
5. 2 阶 + 1 阶
思路:
爬楼梯算是DP的经典题目,递归+记忆化,也就是递推,我们需要定义好状态,还有状态的转移方程。最后爬的步数还是得看之前的,即依赖之前的步骤。
1.反着考虑,有几种方案到第i阶楼梯,答案是2种:
第i-1阶楼梯经过一步
第i-2阶楼梯经过两步
假设count(i)表示到第i阶楼梯方案的个数,则count(i) = count(i-1) + count(i-2)
第一阶是1种,第二阶是2种。代码如下:
class Solution:
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
count = [1,2] #一次就只能走这两步
for i in range(2,n):
count.append(count[i-1]+count[i-2]) #不停地把后面的台阶的结束放到count里面
return count[n-1]
但是太慢了。。。这里起码O(n!)
2.我们想到可以转化为fibonaqi问题。假设一共有10阶楼梯,每步可以爬1步或者2步,那么你爬到10阶一共有两种方法,从8阶爬2步,或从9阶爬1步,那么爬到9阶也是这样,那这就是一共基本的斐波那契数列。
dp[i] = dp[i-1] + dp[i-2]
i-1的时候跳一步可以到达i
i-2的时候跳一步是i-1,这个变成dp[i-1]的子问题了,直接跳两步可以到达i
class Solution:
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
dp = [1 for i in range(n+1)] #状态的定义
for i in range(2,n+1):
dp[i] = dp[i-1]+dp[i-2] #状态转移方程
return dp[n]
这里应该是O(n)
3.还有一种更快速的,列表初始化好,然后再用fibonaqi数列转移方程。
class Solution:
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
condition = [0]*(n+1) #牛逼的初始化列表
condition[0] = 1
condition[1] = 1
for i in range(2,n+1):
condition[i] = condition[i-1]+condition[i-2] #依然还是状态转移fibonaqo
return condition[n]
这里列表初始化只用来O(1),最后复杂度为O(n)