爬楼梯
分析:
首先明确一下:我们默认是站在地面上的,且每次爬可以爬1个或2个台阶。
爬到第1阶台阶 -> 1种
爬到第2阶台阶 -> 2种 :1+1 、 2
爬到第3阶台阶 -> ?
爬到第4阶台阶 -> ?
爬到第 i ( i >= 3) 阶台阶后面就不容易数出来了,所以我们要分析一下爬到第3阶的方法数量 和 爬到第1阶、第2阶的有什么联系
我们是怎么爬到第3阶台阶的?
因为我们只能爬1或2个台阶,
所以我只能是从第2阶台阶通过爬1阶上来 或 从第1阶台阶通过爬2阶上来。
而爬到第1阶时已经有了1种方法,爬到第2阶时已经有了2种方法,所以爬到第3阶的方法数量 = 爬到第1阶时的方法数 + 爬到第2阶时的方法数
这时有的同学可能会有以下疑惑:
(1). 为什么就是两者相加了呢,难道后者的方法中不会有可能包含了前者吗?
答:当然不会,因为前者最后一步是爬了一阶上来的,后者最后一步是爬了两阶上来的。所以两者不可能有重复的方法,结合上方斜体内容理解。
(2). 为什么从第1阶台阶爬到第3阶还是1种,而不是2种;从第2阶台阶爬到第3阶还是2种,而不是3种。为什么爬上来不要+1呢?
答:因为题目要我们求的是有几种方法,而不是几步。当我们打算最后一步是通过爬两个台阶上去时,这就是一个固定的条件了,爬上来了也不会新增一个方法,就是前一步已经有的方法数量。同理,当我们打算最后一步是通过爬一个台阶上去时,这也是一个固定的条件了。多结合上方黑体内容理解下。
[最终个人理解]:
目标为 i 阶台阶时,我们可以选择最后一次抬腿往上爬的动作是爬两阶还是爬一阶到达第i阶台阶。
如果我们选择最后一次抬腿往上爬是爬两阶,那么最后一次为爬两阶的方法数量就是dp[i-2],也就是之前爬到i-2阶时的总方法数量。
如果我们选择最后一次抬腿往上爬是爬一阶,那么最后一次为爬一阶的方法数量就是dp[i-1],也就是之前爬到i-1时的总方法数量。
因为我们最后一次抬腿往上爬既可以选择爬两阶,也可以选择爬一阶,所以爬到第i阶就是两种选择的对应方法数量之和
①dp数组的含义
dp[i] : 爬到第 i 阶台阶有 dp[i] 种方法
②递推公式
爬到第3阶的方法数量 = 爬到第1阶的方法数 + 爬到第2阶的方法数
爬到第n阶的方法数量 = 爬到第n-2阶的方法数 + 爬到第n-1阶的方法数
即 dp[i] = dp[i-2] + dp[i-1]
③初始化
第i阶台阶的方法数依靠前两阶 ( i-1 和 i-1 )得出,所以我们需要至少先知道第一阶和第二阶台阶的方法数,才能根据递推公式推出之后的。
dp[1] = 1;
dp[2] = 2;
④遍历顺序
for(int i = 3; i <= n; i ++)
{
dp[i] = dp[i - 1] + dp[i - 2];
}
完整代码
public int ClimbStairs(int n) {
if(n == 1) return 1;
if(n == 2) return 2;
int[] dp = new int[n+1];
//爬到第i阶有dp[i]种方法
dp[1] = 1;
dp[2] = 2;
for(int i = 3; i <= n; i ++)
{
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}