假设你正在爬楼梯。需要 n
阶你才能到达楼顶。每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入:n = 2 输出:2 解释:有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶
示例 2:
输入:n = 3 输出:3 解释:有三种方法可以爬到楼顶。 1. 1 阶 + 1 阶 + 1 阶 2. 1 阶 + 2 阶 3. 2 阶 + 1 阶
提示:
1 <= n <= 45
思路
本题的实现代码其实和上一道 斐波那契数 是一样的,因为dp数组的初始化以及递推公式、遍历顺序都是一样的。
第一次做动规这道题看下图会更好理解一些。即对于第 i 个台阶,可以从两个前面的台阶爬上去:
- 从 i - 1 处即前一个台阶一次性爬 1 步就可以到达第 i 个台阶
- 从 i - 2 处即前前个台阶一次性爬 2 步就可以到达第 i 个台阶
因此在推出到达第 i 个台阶共有几种方法时需要考虑分别跳到前面紧接着的两个台阶共有多少种方法,递推公式也由此得出。
下面依旧使用动态规划五部曲细说:
dp数组的含义
到达第 i 级楼梯,共有 dp[i] 种方法。
递推公式推导
从上面的分析可以知道,爬到第 i 个台阶可以有两个来源:第 i - 1 个台阶一次性爬 1 步、第 i - 2 个台阶一次性爬 2 步。那么爬到第 i 个台阶的方法数 dp[i] = dp[i - 1] + dp[i - 2]。
dp数组初始化
dp数组初始化看递推公式,从递推公式可以明确,dp数组的第一个与第二个元素需要初始化。dp[1]代表爬到第 1 个台阶的方法数,这自然是 1 种,那 dp[0] 呢?
在做这道题的时候自己也想强行解释一波:因为爬到第 2 个台阶有 2 种方法,为了满足递推公式则初始化为 1,但看了Carl哥的解释后顿悟!其实无需理它 dp[0] 的含义,因为题目给出 n 是大于0的,讨论它没有意义,因此只需初始化为 1 即可。
dp[0] = 1;
dp[1] = 1;
确定遍历顺序
从递推公式来看,求爬到第 i 个台阶的方法数需要 dp[i - 1] 和 dp[i - 2] 是已求得的,故遍历顺序是从左到右的:
for(int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
dp数组举例推导
和上一道斐波那契数是一样的,只不过初始化的值不同罢了,一样的味道!
代码实现
class Solution {
public int climbStairs(int n) {
//1. dp[i]含义: 爬到第i个台阶有dp[i]种方法
int[] dp = new int[n + 1];
//2. 初始化dp数组
dp[0] = 1;
dp[1] = 1;
//4. 遍历
for(int i = 2; i <= n; i++) {
//3. 递推公式
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
}
《代码随想录》刷题记