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

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

目录

  • 题目:
  • 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.lryc.cn/news/105402.html

相关文章:

  • flask---》登录认证装饰器/配置文件/路由系统
  • Jvm实际运行情况-JVM(十七)
  • 【BASH】回顾与知识点梳理(二)
  • 【分布式训练】Accelerate 多卡训练,单卡评测,进程卡住的解决办法
  • 时间复杂度为O(nlogn)的两种排序算法
  • java调用onnx模型,支持yolov5和yolov7
  • DP-GAN损失
  • 自监督去噪:Noise2Void原理和调用(Tensorflow)
  • Mac 安装配置adb命令环境(详细步骤)
  • GDAL C++ API 学习之路 (2) GDALRasterBand篇 代码示例 翻译 自学
  • springboot对静态资源的支持
  • WPF实战学习笔记27-全局通知
  • openSUSE安装虚拟化 qemu kvm
  • 基于linux下的高并发服务器开发(第四章)- 多进程实现并发服务器(回射服务器)
  • 【程序分析】符号执行
  • 实验笔记之——Windows下的Android环境开发搭建
  • #rust taur运行报错#
  • 学习购药系统源码:从前端到后端的技术探索
  • 第九次CCF计算机软件认证
  • 【计算机网络】传输层协议 -- TCP协议
  • Mac上命令
  • 软件安全测试和渗透测试的区别在哪?安全测试报告有什么作用?
  • Android 从LibVLC-android到自编译ijkplayer播放H265 RTSP
  • 如何提升等保水平,减少数据泄露率
  • 蓝桥云课ROS机器人旧版实验报告-07外设
  • sql入门基础-2
  • uni-app:实现表格多选及数据获取
  • 【图论】树上差分(点差分)
  • 【wrk2】轻量级性能测试工具
  • 华为云低代码平台Astro Canvas 搭建汽车展示大屏——实验指导手册