IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode70. 爬楼梯 -> 正文阅读

[数据结构与算法]LeetCode70. 爬楼梯

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/climbing-stairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

假设你正在爬楼梯。需要 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 阶

看到题目感觉像是动态规划的问题,但是for循环的暴力破解应该也可以。写的时候感觉像递归?

(1)动态规划
链接:https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode-solution/
我们用 f(x)f(x) 表示爬到第 xx 级台阶的方案数,考虑最后一步可能跨了一级台阶,也可能跨了两级台阶,所以我们可以列出如下式子:
f(x) = f(x - 1) + f(x - 2)
它意味着爬到第 x级台阶的方案数是爬到第 x - 1级台阶的方案数和爬到第 x - 2级台阶的方案数的和。很好理解,因为每次只能爬 1 级或 2 级,所以 f(x) 只能从 f(x?1) 和 f(x - 2)转移过来,而这里要统计方案总数,我们就需要对这两项的贡献求和。

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

我们不难通过转移方程和边界条件给出一个时间复杂度和空间复杂度都是 O(n) 的实现,但是由于这里的 f(x) 只和 f(x - 1)与 f(x - 2)有关,所以我们可以用「滚动数组思想」把空间复杂度优化成 O(1)。下面的代码中给出的就是这种实现

class Solution:
    def climbStairs(self, n: int) -> int:
        p, q, r = 0, 0, 1
        res = n  # 执行n次
        while res > 0:
            p = q  # f(x-2)
            q = r  # f(x-1)
            r = p + q  #f(x)
            res -= 1
        return r

复杂度分析

时间复杂度:循环执行 nn 次,每次花费常数的时间代价,故渐进时间复杂度为 O(n)O(n)。
空间复杂度:这里只用了常数个变量作为辅助空间,故渐进空间复杂度为 O(1)O(1)。

作者:Gnakuw https://leetcode-cn.com/u/nehzil/
思路:
一般看到题目有多少种方案,这种题意思不需要你列出来具体的多少种方案只需要计算有多少种方案,基本上就可以尝试用动态规划算法来解决问题。想好用动态规划就想想动态规划五步曲。
关键词:有多少种方案 算法

  • 确定dp数组以及下标的含义 定义dp[i]为爬上第 i 级台阶有多少种方案;
  • 确定状态转移方程因为每次只可以爬1或者2个台阶所以,爬上当前台阶的方案应该是前面两个状态的方案的和即,dp[i] = dp[i-1] + dp[i-2]。
  • 初始化状态 i = 0 级开始爬的,所以从第 0 级爬到第 0 级我们可以看作只有一种方案,即 dp(0)=1; i = 1 代表从第 0 级到第 1 级也只有一种方案,即爬一级,dp(1) = 1。
  • 遍历顺序 由状态转移方程知道dp[i] 是从 dp[i?1] 和dp[i?2] 转移过来所以从前往后遍历。
  • 返回值 因为一共计算 n 阶楼梯有多少方案,所以返回dp[n]。

滚动数组的思想
https://blog.csdn.net/m0_46427179/article/details/107419492
滚动数组是一种能够在动态规划中降低空间复杂度的方法,简要来说就是通过观察dp方程来判断需要使用哪些数据,可以抛弃哪些数据,一旦找到关系(递推方程/状态转移方程),就可以用新的数据不断覆盖旧的数据量来减少空间的使用。

(2)矩阵快速幂
https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode-solution/
如何想到使用矩阵快速幂?

(3)通项公式
https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode-solution/
在这里插入图片描述

class Solution:
    def climbStairs(self, n: int) -> int:
        sqrt5 = pow(5, 0.5)  # 根号5
        A = pow(((1 + sqrt5) / 2), n+1)
        B = pow(((1 - sqrt5) / 2), n+1)#公式好像不对,公式是n
        return int((A - B) / sqrt5)  # 计算出来不是整数

(4,5,6的原文地址)
链接:https://leetcode-cn.com/problems/climbing-stairs/solution/zhi-xin-hua-shi-pa-lou-ti-zhi-cong-bao-l-lo1t/
(4)暴力DFS

根据递推公式f(x) = f(x - 1) + f(x - 2) 和边界值,进行递归

class Solution:
    # 暴力深搜
    def climbStairs(self, n: int) -> int:
        if n == 0 or n == 1:#考虑边界
            return 1
        return self.climbStairs(n - 1) + self.climbStairs(n - 2)#还是用递推公式

(5)记忆化递归
将已经算好的值给存起来,等再次需要用到的时候,就直接取而不用计算,这样就大大节省了计算时间

    # 记忆化递归,自顶向下
    def climbStairs(self, n: int) -> int:
        def dfs(i: int, memo) -> int:
            if i == 0 or i == 1:
                return 1
            if memo[i] == -1:
                memo[i] = dfs(i - 1, memo) + dfs(i - 2, memo)
            return memo[i]

        # memo: [-1] * (n - 1)
        # -1 表示没有计算过,最大索引为 n,因此数组大小需要 n + 1
        return dfs(n, [-1] * (n + 1))  #开辟了一个数组,存储算过的值

(6)法一的另一种解法

class Solution:
    # f(n)只依赖于f(n-1)和f(n-2),只需要两项就足够了
    def climbStairs(self, n: int) -> int:
        a = b = 1
        for i in range(2, n + 1):
            a, b = b, a + b
        return b
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 15:57:52  更:2022-05-01 16:01:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:27:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码