【LeetCode】70. 爬楼梯

758 阅读1分钟

「这是我参与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 步,即可求得表达式 f(n)=f(n1)+f(n2)f(n) = f(n-1) + f(n-2)

其含义:要想到达楼顶为 n 级的方法数,得求得到达 n-1 级的方法数和到达 n-2 级的方法数,然后将其合并即可。

以上就是动态规划的转移方程,下面我们来讨论边界条件。我们是从第 0 级开始爬的,所以从第 0 级爬到第 0 级可以看作只有一种方案,即f(0)=1 f(0) = 1;从第 0 级到第 1 级也只有一种方案,即爬一级,f(1)=1f(1) = 1。这两个作为边界条件就可以继续向后推导出第 n 级的正确结果。我们不妨写几项来验证一下,根据转移方程得到 f(2)=2f(2) = 2f(3)=3f(3) = 3f(4)=5f(4) = 5,…,我们把这些情况都枚举出来,发现计算的结果是正确的。

代码

public static int climbStairs(int n) {
    if (n == 0 || n == 1) {
        return n;
    }
    return climbStairs(n - 1) + climbStairs(n - 2);
}

亦或者另一种方法也可:

观察 f(2)f(3)f(4)...f(2)、f(3)、f(4)、... 的结果,可以发现是斐波那契数列,当然这并不是偶然,斐波那契数列就是符合 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)。

结语

业精于勤,荒于嬉;行成于思,毁于随。