题目
来源:0070.爬楼梯
假设你正在爬楼梯。需要 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
分析
爬楼梯问题是动态规划类型中最简单但也最经典的,他和斐波那契数列问题很相似。
我们想象一下,假设你已经用暴力穷举的方法爬到了某一层楼梯,因为一次可以爬 1 个或 2 个台阶, 所以这些方法中,有一部分是你爬到前 1 个台阶再爬 1 个台阶上来的,另一部分是爬到前 2 个台阶再爬两个台阶上来的。
所以爬到第 n
个台阶的方法是爬到第 n - 1
个台阶与爬到第 n - 2
个台阶的方法之和。
再来看最基本的情况,对于 1 个台阶,只能爬 1 阶,也就是 1 种方法;对于 2 个台阶,可以爬两次 1 阶或者爬 1 次 2 阶,方法数为 2;
对于 3 阶,按上述的方法,其方法数是爬 1 阶的方法数和爬 2 阶的方法数之和,也就是 1 + 2 = 3
。
对于 4 阶、5 阶…… 我们都可以用上述方法计算出来。
解答
我们用 dp[i]
表示爬到第 i
阶的方法数,基本情况 dp[1]
, dp[2]
是已知的,
爬到更高的台阶 i
的方法数为 dp[i] = dp[i - 1] + dp[i - 2]
。
public class Solutin {
public int climbStairs(int n) {
if (n < 3) return n;
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];
}
}
这里用了一个数组 dp
来存储爬到第 i
阶的方法数,也可以为了减少内存占用,不使用数组:
public class Solution {
public int climbStairs(int n) {
if (n < 3) return n;
int a = 1;
int b = 2;
int c = 0;
for (int i = 3; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
return c;
}
}