【动态规划】力扣70:爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例:

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1、1 阶 + 1 阶 + 1 阶
2、1 阶 + 2 阶
3、2 阶 + 1 阶

这是十分经典的斐波那契数列题。
定义一个数组 dp, dp[i] 表示走到第 i 阶的方法数。因为我们每次可以走一步或者两步,所以第 i 阶可以从第 i-1 或 i-2 阶到达。换句话说,走到第 i 阶的方法数即为走到第 i-1 阶的方法数加上走到第 i-2 阶的方法数。这样我们就得到了状态转移方程 dp[i] = dp[i-1] + dp[i-2] 。
注意边界条件的处理。
特殊情况:当 n = 1 时,结果为 1 ;当 n = 2 时,结果为 2 。
∴ 完整的状态转移方程为
dp[i] = n, i = 0 或 i = 1; dp[i] = dp[i-1] + dp[i-2], i >= 2。

递归算法:

class Solution:
    def climbStairs(self, n: int) -> int:
        if n <= 0:
            return 0
        elif n <= 2:
            return n
        else:
            dp = [0] * n
            dp[0], dp[1] = 1, 2
            for i in range(2, n):
                dp[i] = dp[i - 1] + dp[i - 2]
            return dp[n - 1]

此代码其实在数组那块有点绕,因为数组时从i = 0开始的。既然是一个斐波那契数列,可以令数组的 i 实际从 1 开始,到 n 结束,每个 i 对应的是实际阶梯。

class Solution:
    def climbStairs(self, n: int) -> int:
        if n <= 0:
            return 0
        elif n <= 2:
            return n
        else:
            dp = [0] * (n + 1) # 创建一个(n+1)维数组,dp[0]无实际意义
            dp[0], dp[1] = 1, 1
            for i in range(2, n + 1): # 依旧从 2 开始,但意义与上面的不同了
                dp[i] = dp[i - 1] + dp[i - 2]
            return dp[n]

渐进时间复杂度为 O(n)。
进一步的,可以对动态规划进行空间压缩。因为 dp[i] 只与 dp[i-1] 和 dp[i-2] 有关,因此可以只用两个变量来存储 dp[i-1] 和 dp[i-2],使得原来的 O(n) 空间复杂度优化为 O(1) 复杂度。

class Solution:
    def climbStairs(self, n: int) -> int:
        if n <= 0:
            return 0
        elif n <= 2:
            return n
        else:
            x, y, temp = 1, 2, 0
            for i in range(2, n):
                temp = x + y
                x, y = y, temp
            return temp
posted @   Vonos  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示