leetcode 70 爬楼梯自己的理解
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
最容易想到的方法就是无脑递归
int climbstairs(int n)
{
if(n==1)
return 1;
else if(n==2)
return 2;
else
return(climbstairs(n-1)+climbstairs(n-1));
}
但是这样做会超时,因为进行了太多重复的计算,比如在计算爬到第3级台阶和计算爬到第4级台阶的时候,都要对第2级台阶进行计算。
第一种解决办法是记忆化递归,就是用一个数组把之前已经计算过的结果把他保存起来:
public class Solution
{
public int climbstairs(int n)
{
int memo[]=new int[n+1];
return climbstairsMemo(n,memo);
}
public int climbstairsMemo(int n,int memo[])
{
if(memo[n]>0)
return memo[n];
if(n==1)
memo[n]=1;
else if(n==2)
memo[n]=2;
else
memo[n]=climbstairsMemo(n-1,memo)+climbstairs(n-2,memo);
return memo[n];
}
}
第二种方法是动态规划
爬到每一级台阶的方法可以看作一个状态,用dp数组来记录状态
public class Solution
{
public int climbstairs(int n)
{
if(n==1)
return 1;
int dp[]=new int[n+1];
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++)
dp[i]=dp[i-1]+dp[i-2];
return dp[n];
}
}
第三种方法是用滚动数组,是对动态规划的改进。
在动态规划中,我们把所有的状态都记录下来了,但是我们可以发现,更新每个状态只会用到这个状态之前的两个状态,所以我们可以用两个变量来记录前两个状态并滚动前进。每次更新后,先把状态1移动到状态2的位置,再把状态2移动到状态3的位置。
public class Solution
{
public int climbstairs(int n)
{
if(n==1)
return 1;
int first=1;
int second=2;
int third;
for(int i=3;i<=n;i++)
{
third=first+second;
first=second;
second=third;
}
return second;
}
}