动态规划篇-01:爬楼梯

这篇具有很好参考价值的文章主要介绍了动态规划篇-01:爬楼梯。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文为力扣70:爬楼梯的详细解析。

虽然这道题的标签是“简单”,但是只有简单的题才能让我们专注于这类题的解题框架上。

一般来说动态规划会有三种解法:暴力解法、使用了备忘录自上而下的递归解法、使用了数组的自下而上的迭代解法。接下来我会对这三种解法逐一演示

70:爬楼梯

动态规划篇-01:爬楼梯,手把手带你刷力扣Hot100,动态规划,算法

根据上文 动态规划篇-00:解题思想与框架 首先我们要明确 [状态转移方程],这样我们就能写出最基础的暴力解法了。

状态转移方程

思考状态转移方程的思路:base case → 明确状态 → 明确路径 → 定义dp函数

base case

在此题中,最小子问题或者说是边界条件就是 “楼梯阶梯数为1或者2的时候”。这个边界问题是根据题意 “你每次可以爬1或2个台阶” 得来的

明确状态

“原问题和子问题中会变化的变量”

此处的 “选择” 为 爬到楼顶的方法

确定选择

“导致状态变化的行为”

此处 “状态” 为楼梯的阶数。正是因为楼梯阶数的变化,导致“爬到楼顶的方法”产生了变化。

定义dp函数

根据题意,自然而然定义 dp(n) 为 “爬上n阶台阶的方法”

我们回想上一篇文章,“[分解问题]思路扩展一下就是动态规划算法”。那么dp(n)的子问题是什么?

我们最后一步是爬上第n阶阶梯,这一步之前我们需要决定是爬1步到n层(dp(n-1))还是爬两步到n层(dp(n-2))。

于是我们根据子问题和上述分析得出了状态转移方程:

动态规划篇-01:爬楼梯,手把手带你刷力扣Hot100,动态规划,算法

状态转移方程中的 “状态转移” 在此处的表现就是:f(n)这个状态可以由 f(n-1) 和 f(n-2) 转移而来

有了状态转移方程就能写出暴力解法了

暴力递归

class Solution {
    public int climbStairs(int n) {   
        return dp(n);
    }
    //定义一个方法dp,表示:有多少种方法爬上n阶阶梯
    public int dp(int n){
        //明确base case
        if(n == 1 || n == 0){
            return 1;
        }
        //写出状态转移方程
        return dp(n-1) + dp(n-2);
    }
}

但是这种解法是通过递归所有可能的情况来得出最终解,时间复杂度较高。这是因为存在大量“重叠子问题”。

比如想要计算 dp(6) ,就要计算dp(5) 和 dp(4)。计算dp(5) 又要计算dp(4) 和 dp(3)。但是dp(4) 已经在计算dp(6) 中计算过了。如果我们用一个备忘录把计算过的结果记录下来,需要的时候直接提取而不是重新计算,那么时间复杂度就会降下来。

使用了备忘录自上而下的递归解法

class Solution {
    public int climbStairs(int n) {
        //定义一个备忘录数组用于记录数据
        int[] memo = new int[n+1];
        return dp(n,memo);
    }
    
    //定义一个方法dp,表示:有多少种方法爬上n阶阶梯
    public int dp(int n,int[] memo){
        //先将备忘录初始化为 -1
        Arrays.fill(memo,-1);
        //base case
        if(n == 1 || n == 0){
            return 1;
        }
        if(memo[n] != -1){
            return memo[n];
        }
        //写出状态转移方程,并更新备忘录
        memo[n] = dp(n-1,memo) + dp(n-2,memo);
        return memo[n];
    }
}

在这种方法中我们使用了一个数组 memo 来记录结果。例如 memo[5] 表示爬上5阶台阶的爬法,对应 dp(5) 的结果。

但是这里有两个问题需要注意:memo数组的长度应该是多少?memo 数组的初始化应该是多少?

问题1: memo数组的长度应该是多少?

我们设定memo数组的长度为 n+1,是为了让memo[n] 对应 dp[n] 的结果,如果memo数组的长度为n的话,memo[n-1] 对应dp(n),dp(0)就只能对应 memo[-1]了。

数组的索引怎么能是 -1 呢?

问题2: memo 数组的初始化应该是多少?

初始化值应该设定为一个 dp 函数无法取到的值。

如果把memo数组中的元素初始化为1。dp(1) = 1,memo[1] = 1。那么我怎么直到这个返回值是dp数组的返回值,还是memo数组初始化的返回值呢?

所以说,初始化值应该设定为一个 dp 函数无法取到的值。

使用了dp数组的自下而上的迭代解法

我们定义一个dp数组,数组元素即为结果。比如dp[n] 定义为 : 爬上n阶阶梯的方法

class Solution {
    public int climbStairs(int n) {
        /*dp[i] 表示的是登录 i层阶梯的方法数量*/
        int[] dp = new int[n+1];
        if(n <= 2){
            return n;
        }
        //base case
        dp[0] = 0;dp[1] = 1;dp[2] = 2;
        for(int i = 3;i <= n;i++){
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];
    }
}

问题1:迭代解法和递归解法的区别

两者的定义起始并无区别。

dp(n) 的定义为 “爬上n阶阶梯的爬法”,dp[n]也是一样的。

dp(n) 是递归解法。比如想要算出dp(4),要算出dp(3) 和dp(2),依次往下,层层递进。直到递进到base case后,拿到数据,在层层回归,得到dp(4)。

而dp[n] 的迭代解法是自下而上的。逐步算出dp[1]、dp[2]、dp[3].....直到算出dp[n]。


那么对于其他题也是如此吗?我们来试试用这个方法算下一道题。文章来源地址https://www.toymoban.com/news/detail-796654.html

到了这里,关于动态规划篇-01:爬楼梯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从0手把手带你搭建pytorch深度学习

    目录 一、查看电脑有NVIDIA显卡没 二、更新电脑驱动 三、安装CUDA ToolKit和CUDNN 1、查看显卡驱动版本 2、查看合适的CUDA版本 3、下载CUDA ToolKit 4、安装CUDA 5、查看是否安装成功 6、安装CUDNN 7、CUDNN配置 四、安装anaconda 五、安装pycharm 六、搭建pytorch深度学习环境 1、进入Anaconda Pr

    2024年02月07日
    浏览(50)
  • 手把手带你实现DQN(TensorFlow2)

            大家好,今天给大家带来DQN的思路及实现方法。         关于DQN,就不用我多做介绍了,我会以最简短明白的阐述讲解DQN,尽量让你在10分钟内理清思路。         非常重要的一点!!!         非常重要的一点!!!我在GitHub上下载了DQN代码,跑完后,我重写一

    2023年04月08日
    浏览(55)
  • 【手把手带你学JavaSE】第六篇:类和对象

    对了!给大家推荐一个刷题学习、面试神器——牛客网 里面有非常多的题库,跟面试经验~非常的良心!! 什么是类? 什么是对象? 怎么去理解这两个抽象的概念呢? Java是一门纯面向对象的语言(Object Oriented Program,继承OOP),在面向对象的世界里,一切皆为对象。 面向对象

    2023年04月20日
    浏览(52)
  • 实战项目:手把手带你实现一个高并发内存池

    1.这个项目做的是什么? 当前项目是实现一个高并发的内存池,他的原型是google的一个开源项目tcmalloc,tcmalloc全称Thread-Caching Malloc,即线程缓存的malloc,实现了高效的多线程内存管理,用于替代系统的内存分配相关的函数(malloc、free)。 2.项目目标 模拟实现出一个自己的高

    2023年04月26日
    浏览(69)
  • 手把手带你啃透比特币白皮书-摘要

    很多人虽然了解了区块链,也可能参与了一些项目,但是可能没有见过比特币白皮书,也没有读过。我接下来就要和大家聊一聊,什么是白皮书,尤其是来给大家精读一下比特币的白皮书。 通过比特币白皮书,你能够 了解到真正的白皮书应该是什么样形式的 。因为很多人可

    2024年02月02日
    浏览(55)
  • 手把手带你做一套毕业设计-征程开启

     本文是《Vue + SpringBoot前后端分离项目实战》专栏的开篇,文本将会包含我们创作这个专栏的初衷,专栏的主体内容,以及我们专栏的后续规划。关于这套毕业设计的作者呢前端部分由狗哥负责,服务端部分则由天哥操刀。我们力求毕业生或者新手通过学完本专栏,可以开心

    2023年04月10日
    浏览(154)
  • 真手把手带你跑r3live

    实验室来了台机器人,上面的设备是依据r3live的设备选的,因为R3LIVE的效果太好了,特别感谢大佬的开源精神。这几天把车子跑起来,就打算写个博客记录一下。 本人能力有限,可能某些地方会有些问题,若发现问题,还请指正。 效果如下: 在多传感器融合slam中,由于会集

    2024年02月09日
    浏览(73)
  • 云原生应用开发,通过一个案例手把手带你入门

    针对云势所趋的市场发展。云计算和云原生应用已经成为主流技术趋势,学习这类技能有远见。可以开发出符合云原生运营模式的应用,满足企业业务发展需要。 实现资源的高效利用和弹性扩展。通过微服务架构、容器技术、弹性计算等手段,构建出计算资源利用高、扩展灵活的

    2024年02月06日
    浏览(63)
  • 【reverse】手把手带你基于dll实现多次SMC

    SMC,即self modifying code,自修改代码,逆向入门SMC可以看一下我的题解。我打算实现一个类似于【网鼎杯2020青龙组】jocker的SMC方案。这个方案不需要用到汇编,因此门槛极低( 连小小前端都能学会 )。为什么要基于dll呢?因为代码段加密功能是通过外部python脚本完成的,将自

    2024年02月02日
    浏览(55)
  • 手把手教你 ,带你彻底掌握八大排序算法【数据结构】

    直接插入排序是一种简单的插入排序法,其基本思想:是把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 可以理解为一遍摸扑克牌,一边进行排序 在待排序的元素中,假设前面n-1(其中n=2)个数

    2024年02月02日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包