三步问题(力扣)n种解法 JAVA

news2024/9/27 19:18:07

目录

  • 题目:
  • 1、dfs:
  • 2、dfs + 备忘录(剪枝):
    • (1)神器 HashMap 备忘录:
    • (2)数组 memo 备忘录:
  • 3、动态规划:
  • 4、利用 static 的储存功能:
    • (1)static 修饰 HashMap:
    • (2)static 修饰 memo 数组:
    • (3)static 修饰 dp 数组 + 动态规划:
  • 5、动态规划 + 优化常数空间:
  • 6、数学 矩阵:

题目:

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

示例1:

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

示例2:

输入:n = 5
输出:13

提示:

n范围在[1, 1000000]之间

解题思路:

记得多次取模防止爆掉int

1、dfs:

class Solution {
	int INF = 1000000007;
    public int waysToStep(int n) {
          return dfs(n) % INF;
    }
    public int dfs(int n) {
    	 if(n < 0) return 0;
         if(n == 0) return 1;
         return ((dfs(n - 1) + dfs(n - 2)) % INF + dfs(n - 3)) % INF;
    }
}

在这里插入图片描述

显然超时,得剪枝


2、dfs + 备忘录(剪枝):

(1)神器 HashMap 备忘录:

class Solution {
	int INF = 1000000007;
	Map<Integer, Integer> map = new HashMap<>();
    public int waysToStep(int n) {
          map.put(0, 1);
          return dfs(n) % INF;
    }
    public int dfs(int n) {
    	if(n < 0) return 0;
    	if(map.containsKey(n)) return map.get(n);
        int ans = ((dfs(n - 1)  + dfs(n - 2)) % INF + dfs(n - 3)) % INF;
        map.put(n, ans);
        return ans;
    }
}

在这里插入图片描述
在这里插入图片描述
当然神器也是有缺陷的即查询需要些许时间,可以试试用数组当备忘录

(2)数组 memo 备忘录:

class Solution {
	int INF = 1000000007;
	public static int memo[];
    public int waysToStep(int n) {
    	  memo = new int[n + 1];
          memo[0] = 1;
          return dfs(n) % INF;
    }
    public int dfs(int n) {
    	if(n < 0) return 0;
    	if(memo[n] != 0) return memo[n];
    	int ans = ((dfs(n - 1) + dfs(n - 2)) % INF + dfs(n - 3)) % INF;
    	memo[n] = ans;
    	return memo[n];
    }
}

在这里插入图片描述

在这里插入图片描述
速度快了不少,还有突破空间


3、动态规划:

代码:

class Solution {
    public int waysToStep(int n) {
        if(n <= 2) return n;
        if (n == 3) return 4;
        int[] d = new int[n + 1];
        d[1] = 1;
        d[2] = 2;
        d[3] = 4;
        for (int i = 4; i <= n; i++){
            d[i] = (d[i-1] + d[i-2]) % 1000000007 +d[i-3];
            d[i] %= 1000000007;
        }
        return d[n];
    }
}

在这里插入图片描述
在这里插入图片描述

不太理解为什么会比 dfs + 剪枝快这么多,这里给出的猜测是递归压栈耗费了大量时间

当然26ms还有突破空间


4、利用 static 的储存功能:

之前提到过Java的static修饰变量是有存储功能的不会因为创建新对象就恢复初始化

static简述 JAVA

(1)static 修饰 HashMap:

代码:

class Solution {
	int INF = 1000000007;
	public static Map<Integer, Integer> map = new HashMap<>();
    public int waysToStep(int n) {
          map.put(0, 1);
          return dfs(n);
    }
    public int dfs(int n) {
    	if(n < 0) return 0;
    	if(map.containsKey(n)) return map.get(n);
        int ans = ((dfs(n - 1)  + dfs(n - 2)) % INF + dfs(n - 3)) % INF;
        map.put(n, ans);
        return ans;
    }
}

在这里插入图片描述

在这里插入图片描述
时间大概降了一半

(2)static 修饰 memo 数组:

为了更好储存memo数组要设置最大长度

代码:

class Solution {
	int INF = 1000000007;
	public static int memo[] = new int[1000001];
    public int waysToStep(int n) {
          memo[0] = 1;
          return dfs(n) % INF;
    }
    public int dfs(int n) {
    	if(n < 0) return 0; 
        if(memo[n] != 0) return memo[n];
    	int ans = ((dfs(n - 1) + dfs(n - 2)) % INF + dfs(n - 3)) % INF;
    	memo[n] = ans;
    	return memo[n];
    }
}

在这里插入图片描述
在这里插入图片描述
速度也是之前的一半


(3)static 修饰 dp 数组 + 动态规划:

充分利用了动态规划的高效以及static的存储功能设立static变量j避免重复更新数据

代码:

class Solution {
	public static int dp[] = new int[1000000];
	public static int j;
    public int waysToStep(int n) { 
        if(dp[n] != 0) return dp[n];
        if(n <= 2) return n;
        if (n == 3) return 4;
        if(j < 3){
         dp[0] = 1;
         dp[1] = 1;
         dp[2] = 2;
         dp[3] = 4;
         j  = 4;
        } 
        for (int i = j; i <= n; i++) dp[i] = ((dp[i-1] + dp[i-2]) % 1000000007 +dp[i-3]) % 1000000007;
        j = n;
        return dp[n];
    }
}

在这里插入图片描述

在这里插入图片描述
偶然能触及12ms的边边


5、动态规划 + 优化常数空间:

代码:

class Solution {
    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, d;
        while (--n >= 3) {
            d = a + b + c;
            a = b;
            b = c;
            c = d % 1000000007;
        }
        return (int) c;
    }
}

在这里插入图片描述

在这里插入图片描述

这是网上大佬写的也这么快是我没想到的

目前猜测唯一可能是static修饰变量每次创建新对象仍要创建一次数组,且创建数组需要耗费很多时间


6、数学 矩阵:

class Solution {
    public static int  waysToStep(int n) {
        if (n == 1) {
            return 1;
        }
        if (n == 2) {
            return 2;
        }
        if (n == 3) {
            return 4;
        }
        long[][] m = {{1, 1, 1}, {1, 0, 0}, {0, 1, 0}};
        long[][] mn = pow(m, n - 3);
        long res = (mn[0][0] * 4 + mn[0][1] * 2 + mn[0][2] * 1) % 1000000007;
        return (int) res;
    }

    public static long[][] pow(long[][] a, int i) {
        long[][] val = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
        while (i != 0) {
            if ((i % 2) == 1)  {
                val = multiply(val, a);
            }
            a = multiply(a, a);
            i = i / 2;
        }
        return val;
    }


    public static long[][] multiply(long[][] a, long[][] b) {
        long[][] c = new long[3][3];
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                long s = 0;
                for (int k = 0; k < 3; k++) {
                    s = (s + (a[i][k] % 1000000007 * b[k][j] % 1000000007)) % 1000000007;
                }
                c[i][j] = s % 1000000007;
            }
        }
        return c;
    }
}
 

在这里插入图片描述

网上大佬写的,真快,给我看傻了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/809134.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ - stack 和 queue 模拟实现 -认识 deque 容器 容器适配器

stack模拟实现 用模版实现 链式栈 和 顺序栈 对于stack 的实现&#xff0c;有两种方式&#xff0c;一种是连续空间存储的顺序栈&#xff0c;一种是不连续空间存储的链式栈&#xff0c;在C当中如果要使用两种不同的栈的话&#xff0c;实现方式是不一样的&#xff0c;他们的底层逻…

Transformer背景介绍

目录 Transformer的诞生Transformer的优势Transformer的市场 Transformer的诞生 论文地址 Transformer的优势 Transformer的市场

【MySQL】事务管理

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《零基础入门MySQL》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录 &#x1f449;CU…

使用mediapipe训练手指数字识别

mediapipe手指数字识别 本文是从0开始创建一个识别手势的机器学习模型&#xff0c;为了识别手势&#xff0c;采用mediapipe模型&#xff0c;这个模型会返回手指的位置&#xff0c;之后再通过训练一个模型将这些位置分类得到手势 一、导入依赖 import cv2 import numpy as np…

分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离(一)

说明&#xff1a;请先自行安装好docker再来看本篇文章&#xff0c;本篇文章主要实现通过使用docker部署mysql实现读写分离&#xff0c;并连接数据库测试。第二篇将实现使用Shardingjdbc实现springboot的读写分离实现。 基于Docker去创建Mysql的主从架构 #创建主从数据库文件夹…

小黑子—JavaWeb:第四章 Request与Response

JavaWeb入门4.0 1. Request(请求)& Response (响应)2. Request2.1 Request 继承体系2.2 Request 获取请求数据2.2.1 通用方式获取请求参数2.2.2 IDEA模板创建Servlet2.2.3 请求参数中文乱码处理2.2.3 - I POST解决方案2.2.3 - II GET解决方案 2.3 Request 请求转发 3. Resp…

常见网关对比

常见网关对比 目前常见的开源网关大致上按照语言分类有如下几类&#xff1a; Nginxlua &#xff1a;OpenResty、Kong、Orange、Abtesting gateway 等 Java &#xff1a;Zuul/Zuul2、Spring Cloud Gateway、Kaazing KWG、gravitee、Dromara soul 等 Go &#xff1a;Janus、fa…

简单学会MyBatis原生API注解

&#x1f600;前言 本篇博文是关于MyBatis原生API&注解的使用&#xff0c;希望能够帮助到你&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您…

2023深圳杯数学建模B题

B题 电子资源版权保护问题 版权又称著作权&#xff0c;包括发表权、署名权、修改权、保护作品完整权、复制权、发行权、出租权、展览权、表演权、放映权、广播权、信息网络传播权、摄制权、改编权、翻译权、汇编权及应当由著作权人享有的其他权利。 在计算机网络广泛应用的今…

39.手机导航

手机导航 html部分 <div class"phone"><div class"content"><img class"active" src"./static/20180529205331_yhGyf.jpeg" alt"" srcset""><img src"./static/20190214214253_hsjqw…

基于 ThinkPHP 5.1(稳定版本) 开发wms 进销存系统源码

基于ThinkPHP 5.1&#xff08;LTS版本&#xff09;开发的WMS进销存系统源码 管理员账号密码&#xff1a;admin 一、项目简介 这个系统是一个基于ThinkPHP框架的WMS进销存系统。 二、实现功能 控制台 – 权限管理&#xff08;用户管理、角色管理、节点管理&#xff09; – 订…

BUUCTF——reverse3 适合新手的关于base64加密算法代码的分析

作为一个逆向小白&#xff0c;学了点加密算法就来BUU找点乐子&#xff0c;前7题蛮简单的&#xff0c;然后做到了reverse3&#xff0c;典型的base64加密算法&#xff0c;让我折腾了好久&#xff0c;写篇博客记录一下 顺便说下很多博客并没有对这里的加密算法进行代码上的分析&a…

秋招备战笔试Day1

目录 单选 1. 在 Java 中&#xff0c;存放字符串常量的对象属于&#xff08; &#xff09;类对象。 2.已知如下类定义&#xff1a; 如下哪句可以正确地加入子类中&#xff1f; 3. 下列选项中属于面向对象编程主要特征的是&#xff08;&#xff09; 4.关于下列程序段的输出结…

并发编程可能出现的核心问题

2.1非可见性 如果主内存里有个静态变量flagfalse&#xff0c;然后线程A和B在工作内存都需要操作flag&#xff0c;线程A是while(!false){}&#xff0c;而线程B将flag改为true&#xff0c;但是由于线程A和线程B之间工作内存互相不可见&#xff0c;线程A就会陷入死循环。 2.2指令…

排序链表——力扣148

文章目录 题目描述法一 自顶向下归并排序法二&#xff09;自底向上归并排序 题目描述 题目的进阶问题要求达到 O(nlogn) 的时间复杂度和 O(1) 的空间复杂度&#xff0c;时间复杂度是 O(nlogn) 的排序算法包括归并排序、堆排序和快速排序&#xff08;快速排序的最差时间复杂度是…

【RabbitMQ(day2)】默认(直连)交换机的应用

文章目录 一、第一种模型&#xff08;Hello World&#xff09;二、第二种模型&#xff08;work queue&#xff09;自动确认机制的后果和公平分配 三、阐述默认交换机 这篇博客是以下资料学后的总结&#xff1a; 不良人的RabbitMQ的教学视频 官方启动教程 RabbitMQ中文文档 一、…

php 生成连续递增的Excel列索引 可以控制多少列

今天遇到需要生成对应的下拉&#xff0c;下拉的类 需要PHP 输出一个数组 如 A、B、C、D 到Z 列后 Excel 的列就变成 AA 、AB、 AC 依次类推 查询得知 Excel 最大列数 16384 最大行数 1048576 下面演示3000列或行 <?php$idx [idx > 0];for ($i …

WIZnet W6100-EVB-Pico 静态IP配置教程(二)

W6100是全球第一款支持IPv4/IPv6双核的新一代全硬件以太网TCP/IP协议栈控制器。W6100在WIZnet核心专利技术——全硬件TCP/IP协议栈IPv4的基础上增加了IPv6&#xff0c;解决了嵌入式以太网的接入问题&#xff0c;简单易用&#xff0c;安全稳定&#xff0c;是物联网设备的首选解决…

某文化馆三维建模模型-glb格式-三维漫游-室内导航测试

资源描述 某文化馆某个楼层的三维建模模型&#xff0c;glb格式&#xff0c;适用于three.js开发&#xff0c;可用来做一些三维室内漫游测试和室内导航测试 资源下载地址

Java框架学习(三)spring5高级49讲

文章目录 1、BeanFactory与ApplicationContext2、BeanFactory与ApplicationContext的容器实现BeanFactory的容器实现后处理器排序 ApplicationContext的容器实现 3、Bean的生命周期Bean后处理器 4、常见的Bean后处理器5、常见BeanFactory后处理器6、Aware和InitializingBean接口…