「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。
题目
假设你正在爬楼梯。需要 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
我的题解
思路
穷举法?得了吧。如果正向思考的话,那有点毫无头绪,我们试着逆向思考下:我们目前走到了最后一步,根据题意,最后一步到达楼顶的方式有 2 种:1 步或 2 步,即可求得表达式 。
其含义:要想到达楼顶为 n 级的方法数,得求得到达 n-1 级的方法数和到达 n-2 级的方法数,然后将其合并即可。
以上就是动态规划的转移方程,下面我们来讨论边界条件。我们是从第 0 级开始爬的,所以从第 0 级爬到第 0 级可以看作只有一种方案,即;从第 0 级到第 1 级也只有一种方案,即爬一级,。这两个作为边界条件就可以继续向后推导出第 n 级的正确结果。我们不妨写几项来验证一下,根据转移方程得到 ,,,…,我们把这些情况都枚举出来,发现计算的结果是正确的。
代码
public static int climbStairs(int n) {
if (n == 0 || n == 1) {
return n;
}
return climbStairs(n - 1) + climbStairs(n - 2);
}
亦或者另一种方法也可:
观察 的结果,可以发现是斐波那契数列,当然这并不是偶然,斐波那契数列就是符合
f(n) = f(n-1) + f(n-2)公式。
public int climbStairs(int n) {
int p = 0, q = 0, r = 1;
for (int i = 1; i <= n; ++i) {
p = q;
q = r;
r = p + q;
}
return r;
}
时间复杂度:循环执行 n 次,每次花费常数的时间代价,故渐进时间复杂度为 O(n)。
空间复杂度:这里只用了常数个变量作为辅助空间,故渐进空间复杂度为 O(1)。
结语
业精于勤,荒于嬉;行成于思,毁于随。