链接:https://leetcode-cn.com/problems/climbing-stairs/
假设你正在爬楼梯。需要 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 个台阶或者 2 个台阶。
当我们位于某一个台阶时,我们有两种爬法,爬 1 个台阶或者 2 个台阶。即假设我们到达第 n 个台阶时,我们可能是从第 n-1 台阶或者第 n-2 台阶爬上来的。
根据以上分析,我们可以得到如下公式:
f(n)=f(n-1)+f(n-2)
时间复杂度O(2^n
空间复杂度:O(n)
class Solution:
def climbStairs(self, n: int) -> int:
if n<=2:
return n
return self.climbStairs(n-1)+self.climbStairs(n-2)
以上的递归肯定超时,所以我们使用记忆化递归优化。
时间复杂度:O(n)
空间复杂度:O(n)
class Solution:
def climbStairs(self, n: int) -> int:
def dfs(i, memo):
if i<=2:
return i
if memo[i] == 0:
memo[i] = dfs(i-1,memo)+dfs(i-2,memo)
return memo[i]
return dfs(n,[0]*(n+1))
定义数组元素的含义
找出数组元素间的关系式
从递归的解法可以看出,我们可以把一个大规模问题分成几个小规模问题,然后由小的问题推导出大的问题;
因为到达第 n 级的台阶有两种方式:一种是从第 n-1 级跳上来,另一种是从第 n-2 级跳上来;
所以:dp[n] = dp[n-1] + dp[n-2]。
找出初始值
当 n=1 时,dp[1]=dp[0]+dp[-1],不允许下标为-1,所以使用 dp[0] 和 dp[-1] 作为初始值不合适。
如果定义初始值 dp[0]=0,dp[1]=1,当 n=2 时,dp[2]=dp[1]+dp[0]=1,但实际上 n=2 时有 2 种爬法,即 dp[2]=2,所以以上初始值定义不严谨。
所以,我们定义初始值 dp[1]=1,dp[2]=2,循环从 3 开始。当然,你也可以定义 dp[0]=1,dp[1]=1,然后循环从 2 开始。
时间复杂度:O(n)
空间复杂度:O(n)
class Solution:
def climbStairs(self, n: int) -> int:
if n<=2:
return n
dp=(n+1)*[0]
dp[1]=1
dp[2]=2
for i in range(3,n+1):
dp[i]=dp[i-1]+dp[i-2]
return dp[n]
因为动态规划解法时使用了数组,空间复杂度为 O(n),我们可以通过两个变量将空间复杂度降为 O(1)。
时间复杂度:O(n)
空间复杂度:O(1)
class Solution:
def climbStairs(self, n: int) -> int:
if n<=2:
return n
dp1=1
dp2=2
for i in range(3,n+1):
dp1,dp2=dp2,dp1+dp2
return dp2
如果觉得文章还不错的话,可以关注我,我会定期分享的。