当前位置: 首页 > article >正文

【LeetCode: 面试题 08.01. 三步问题 | 暴力递归=>记忆化搜索=>动态规划】

在这里插入图片描述

🍎作者简介:硕风和炜,CSDN-Java领域新星创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎
🍎座右铭:人生如棋,我愿为卒,行动虽慢,可谁曾见我后退一步?🎯🎯🎯

在这里插入图片描述

目录

    • 题目链接
    • 题目描述
    • 求解思路&实现代码&运行结果
      • 暴力递归
        • 求解思路
        • 实现代码
        • 运行结果
      • 记忆化搜索
        • 求解思路
        • 实现代码
        • 运行结果
      • 动态规划
        • 求解思路
        • 实现代码
        • 运行结果
    • 课后任务
      • 状态压缩
      • 运行结果
    • 共勉

题目链接

面试题 08.01. 三步问题

题目描述

三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。

示例1:
输入:n = 3
输出:4
说明: 有四种走法

示例2:
输入:n = 5
输出:13

提示:
n范围在[1, 1000000]之间

求解思路&实现代码&运行结果

暴力递归

求解思路

在这里插入图片描述

实现代码

class Solution {

    public final int mod=1000000007;

    public int waysToStep(int n) {
        if(n==1) return 1;
        if(n==2) return 2;
        if(n==3) return 4;
        return (waysToStep(n-1)%mod+waysToStep(n-2)%mod+waysToStep(n-3)%mod)%mod; 
    }
}

运行结果

根据我们代码提交的结果来看,不出我们所料,直接时间超限,但是所有的事情并不是绝对的,或者都是坏的,都是好的,虽然时间超限,但是侧面验证了我们的思路是正确的,对吧,接下来我们就有大致的改进方向了。

在这里插入图片描述

记忆化搜索

求解思路

  1. 根据我们递归的分析,在递归的过程中会产生重复的子过程,为了改进这个过程,避免重复计算的问题,此时我们想到的解决方案就是加一个缓存表,也就是我们的记忆化搜索。
  2. 具体实现的相关细节请看具体的代码。

实现代码

class Solution {

    public final int mod=1000000007;
    
    public int waysToStep(int n) {
        long[] dp=new long[1000010];
        return (int)(waysToStep(n,dp)); 
    }

    public long waysToStep(int n,long[] dp) {
        if(dp[n]!=0) return dp[n];
        if(n==1) return dp[n]=1;
        if(n==2) return dp[n]=2;
        if(n==3) return dp[n]=4;
        return dp[n]=(waysToStep(n-1,dp)%mod+waysToStep(n-2,dp)%mod+waysToStep(n-3,dp)%mod)%mod; 
    }
}

运行结果

之前的暴力递归过都过不了,此时我们可以看到记忆化缓存已经可以勉强通过了,撒花啦。。。
但是,有的同学可不想止步于此呢?那么怎么做呢?我们就需要继续进行改进了,也就是接下来的动态规划版本。
在这里插入图片描述

动态规划

求解思路

  1. 那动态规划怎么做呢?怎么改进呢?接下来我们就要根据这个递归的过程去求解动态规划的递推公式,也就是我们常说的状态转移。
  2. 具体过程如下图所示:
    在这里插入图片描述

实现代码

class Solution {

    public final int mod=1000000007;
    
    public int waysToStep(int n) {
        long[] dp=new long[1000010];
        dp[1]=1;
        dp[2]=2;
        dp[3]=4;
        for(int i=4;i<=n;i++){
            dp[i]=(dp[i-1]%mod+dp[i-2]%mod+dp[i-3]%mod)%mod;
        }
        return (int)(dp[n]); 
    }

}

运行结果

此时呢,最终的动态规划的版本就出来了,大家可以看到,一步一步走来有理有据,比起我们直接去想这个最终的动态规划是不是更好理解呢?
在这里插入图片描述

课后任务

虽然上面我们已经求得了最终的动态规划,此时的时间复杂度已经达到最优了O(n),但是大家有没有发现一个问题,此时的空间复杂度还是可以继续进行优化的,优化的方法是什么呢?也就是我们常说的状态压缩,那么这个任务就留给你了,下来一定要动手亲自实操一下,把它实现,我把代码贴到这里,大家可以参考一下。

状态压缩

class Solution {

    public final int mod=1000000007;
    
    public int waysToStep(int n) {
        if(n==1) return 1;
        if(n==2) return 2;
        if(n==3) return 4;
        long a=1,b=2,c=4;
        long ans=0;
        for(int i=4;i<=n;i++){
            ans=(a%mod+b%mod+c%mod)%mod;
            a=b;
            b=c;
            c=ans;
        }
        return (int)(ans); 
    }

}

运行结果

在这里插入图片描述

共勉

最后,我想送给大家一句一直激励我的座右铭,希望可以与大家共勉!
在这里插入图片描述

在这里插入图片描述


http://www.kler.cn/a/7618.html

相关文章:

  • 前端怎么获取视口大小
  • AlphaFold3中文使用说明
  • ElasticSearch-全文检索(一)基本介绍
  • 蓝桥杯竞赛单片机组备赛【经验帖】
  • 使用CNN进行验证码识别:深度学习与图像预处理教程
  • 第四十五章 Vue之Vuex模块化创建(module)
  • go : 支持的设计模式
  • PyTorch随笔 - Glow: Generative Flow with Invertible 1×1 Convolutions
  • springboot(07)邮件发送(qq邮箱)
  • 大地量子与亚马逊云科技合作,为新能源业务的发展提供更多的最佳实践
  • P1010 [NOIP1998 普及组] 幂次方
  • JAVASE 继承
  • 【python+requests】接口自动化测试
  • try catch的应用
  • python--虚拟环境搭建(使用命令安装)
  • 【ESP-IDF】你好世界
  • “智慧”的大楼,为啥落地这么难?
  • Java GenericObjectPool 对象池化技术--SpringBoot sftp 连接池工具类
  • 有些人失业是必然的,AIGC使用两周后体验
  • Python 3.7 有什么新变化 - 其他语言更改新模块
  • Python中request与Requests.request与session.reauest,session.reauest实现自动关联
  • 【第一节】- flink源码编译
  • USB土壤参数检测仪丨便捷、全面、耐用
  • fiddler(抓包)的用法和HTTP 协议的基本格式
  • 科特ECTN快捷办理
  • LinkedHashMap源码分析以及LRU的应用