在问 · 算法题解

70. 爬楼梯

简单动态规划动态规划(滚动变量)力扣原题 ↗

题目描述

一段楼梯共有 n 级台阶。每一步可以上 1 级,也可以上 2 级。

返回从地面走到第 n 级共有多少种不同的走法。两种走法只要某一步的步长序列不同,就算不同。

示例 1
输入:n = 2
输出:2

解释:两种走法:1+1,或者 2。

示例 2
输入:n = 3
输出:3

解释:三种走法:1+1+1、1+2、2+1。

数据范围

  • 1 <= n <= 45

解题思路:动态规划(滚动变量)

到第 i 阶只能从 i-1 或 i-2 来,因此滚动保存两个前状态。

为什么正确

完成 k 次循环后,a=f(k)、b=f(k+1);完成 n 次后返回 a。

复杂度分析

时间 O(n),空间 O(1)。

易错点

初始值是 f(0)=1,表示空走法;错设为 0 会让整个序列偏移。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def climbStairs(self, n: int) -> int:
        a, b = 1, 1
        for _ in range(n):
            a, b = b, a + b
        return a

载入编辑器,自己跑一遍 →

其他解法

滚动变量 O(n) 最简单;矩阵快速幂 O(log n),适合 n 极大或需要取模的线性递推题。

解法 2:矩阵快速幂 时间 O(log n),空间 O(1)

递推 f(n)=f(n-1)+f(n-2) 可以写成矩阵形式:[f(n+1), f(n)] = [[1,1],[1,0]] × [f(n), f(n-1)]。因此 f(n) 等于矩阵 [[1,1],[1,0]] 的 n 次幂左上角的元素。用快速幂把 n 按二进制拆开,只做 O(log n) 次 2×2 矩阵乘法。

n 很大时明显更快,而且这个套路可以推广到任意线性递推。代码比滚动变量长,本题 n ≤ 45 时并没有实际收益。

class Solution:
    def climbStairs(self, n: int) -> int:
        def mul(a, b):
            return [
                [a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]],
                [a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]],
            ]

        res = [[1, 0], [0, 1]]
        base = [[1, 1], [1, 0]]
        while n > 0:
            if n & 1:
                res = mul(res, base)
            base = mul(base, base)
            n >>= 1
        return res[0][0]

动态规划 专题的其他题目

查看 动态规划 全部题目 →