记忆化搜索专题——算法简介力扣实战应用
目录
1、记忆化搜索算法简介
1.1 什么是记忆化搜索
1.2 如何实现记忆化搜索
1.3 记忆化搜索与动态规划的区别
2、算法应用【leetcode】
2.1 题一:斐波那契数
2.1.1 递归暴搜解法代码
2.1.2 记忆化搜索解法代码
2.1.3 动态规划解法代码
2.2 题二:不同路径
2.2.1 算法原理
2.2.2 记忆化搜索代码
2.2.3 动态规划代码
2.3 题三:最长递增子序列
2.3.1 算法原理
2.3.2 记忆化搜索代码
2.3.3 动态规划代码
2.4 题四:猜数字大小II
2.4.1 算法原理
2.4.2 算法代码
2.5 题五:矩阵中的最长递增路径【困难】
2.5.1 算法原理
2.5.2 算法代码
1、记忆化搜索算法简介
1.1 什么是记忆化搜索
记忆化搜索(Memoization)是一种优化搜索算法的技术,主要用于减少重复计算,提高算法效率。它通过存储已经计算过的结果来避免对同一问题的重复计算,特别适用于递归算法中存在大量完全重复的递归的情况。
简单来说,记忆化搜索就是带备忘录的递归。
举个例子,当我们使用普通的暴搜递归法求斐波那契数时,意味着每个节点都需要遍历一遍,时间复杂度为O(2^N),但是这其中出现大量完全重复的递归树,大量重复的递归导致时间效率严重降低。这时,我们就可以使用一个“备忘录”所出现过的数据存起来,递归时若遇见重复的问题时,直接从“备忘录”中取值即可,不必再次重复递归。这样一来,我们可将时间复杂优化为线性级别:O(N)。
我们以添加“备忘录”的形式,将数据记忆起来,减少大量重复的递归,这样的暴搜优化( O(2^N) --> O(N) )算法就称为记忆化搜索。
注意:
并非所有的递归暴搜都可改为记忆化搜索,只有在递归的过程中,出现了大量完全相同的问题时(并非相同子问题),才可以使用记忆化搜索进行优化。
1.2 如何实现记忆化搜索
- 添加备忘录 ---> <可变参数,返回值>
- 每次进入递归的时候,瞅一瞅备忘录里面是否已存在想要的结果
- 每次递归返回的时候,将结果放到备忘录中存起来
1.3 记忆化搜索与动态规划的区别
其实记忆化搜索与动态规划本质上都是一回事。
- 都属于暴力解法(暴搜)
- 都是对暴搜的优化:把计算过的值,存起来
但是不同的是:
- 记忆化搜索是以递归的形式进行的
- 动态规划是以递推(循环)的形式进行的
- 记忆化搜索是自顶向下(dfs(n) --> dfs(n-1) 、 dfs(n-2))
- 动态规划是自底向上(dp[1] 、 dp[2] --> dp[3] )
2、算法应用【leetcode】
2.1 题一:斐波那契数
. - 力扣(LeetCode)
相信对于斐波那契数的计算,大家都已了然于心,这里就不多废话了,只向大家展示三中不同解法:
- 递归暴搜解法:O(2^N)
- 记忆化搜索解法(暴搜优化):O(N)
- 动态规划解法(暴搜优化):O(N)
2.1.1 递归暴搜解法代码
class Solution {public int fib(int n) {return dfs(n);}public int dfs(int n) {if(n == 0 || n == 1) return n;return dfs(n - 1) + dfs(n - 2);}
}
2.1.2 记忆化搜索解法代码
class Solution {//记忆化搜索int[] memo;//memorypublic int fib(int n) {memo = new int[31];Arrays.fill(memo, -1);//初始化时,填入不可能出现的值return dfs(n);}public int dfs(int n) {if(memo[n] != -1) return memo[n];if(n == 0 || n == 1) {memo[n] = n;return n;}memo[n] = dfs(n - 1) + dfs(n - 2);return memo[n];}
}
2.1.3 动态规划解法代码
class Solution {//动态规划int[] dp;public int fib(int n) {dp = new int[31];dp[0] = 0; dp[1] = 1;for(int i = 2; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}
}
2.2 题二:不同路径
. - 力扣(LeetCode)
2.2.1 算法原理
经过分析,可以发现:到达(x,y)位置的路径数=到达(x,y-1)的路径数+到达(x-1,y)的路径数
设计递归函数体:dfs(m,n) = dfs(m,n-1)+dfs(m-1,n)
函数出口:
- if(m == 0 || n == 0) return 0;(从下标1开始为有效位置)
- if(m== 1&&n ==1) return 1;//特殊处理
经过验证,纯暴搜解法是会超时的,经分析,问题中出现了大量重复的问题,采取记忆化搜索算法和动态规划进行优化。
2.2.2 记忆化搜索代码
class Solution {//记忆化搜索int[][] memo;public int uniquePaths(int m, int n) {//从下标1,1开始memo = new int[m + 1][n + 1];return dfs(m, n);}public int dfs(int m, int n) {if(memo[m][n] != 0) return memo[m][n];if(m == 0 || n == 0) {return 0;}if(m == 1 && n == 1) {memo[m][n] = 1;return 1;}memo[m][n] = dfs(m, n - 1) + dfs(m - 1, n);return memo[m][n];}
}
2.2.3 动态规划代码
class Solution {public int uniquePaths(int m, int n) {//动态规划int[][] dp = new int[m + 1][n + 1];dp[1][1] = 1;for(int i = 1; i < m + 1; i++) {for(int j = 1;j < n + 1; j++) {if(i == 1 && j == 1) continue;dp[i][j] = dp[i][j - 1] + dp[i - 1][j];}}return dp[m][n];}
}
2.3 题三:最长递增子序列
2.3.1 算法原理
因为是最长递增子序列,所以只能从当前位置向后找。
- 函数头:dfs(pos);//pos位置处的最长子序列
- 从当前位置pos开始,选出后面位置中最长的子序列len(注意:要求nums[i] > nums[pos]),再得len+1(当加上前位置),就是当前位置的最长子序列。
2.3.2 记忆化搜索代码
class Solution {//记忆化搜索int n;public int lengthOfLIS(int[] nums) {int ret = 0;n = nums.length;int[] memo = new int[n];for(int i = 0; i < n; i++) {ret = Math.max(ret, dfs(nums, i, memo));}return ret;}public int dfs(int[] nums, int pos, int[] memo) {if(memo[pos] != 0) return memo[pos];int ret = 1;for(int i = pos + 1; i < n; i++) {if(nums[i] > nums[pos]) {ret = Math.max(ret, dfs(nums, i, memo) + 1);}}memo[pos] = ret;return ret;}
}
2.3.3 动态规划代码
class Solution {//动态规划int n;public int lengthOfLIS(int[] nums) {int ret = 0;n = nums.length;int[] dp = new int[n];Arrays.fill(dp, 1);for(int i = n - 1; i >= 0; i--) {for(int j = i + 1; j < n; j++) {if(nums[i] < nums[j]) {dp[i] = Math.max(dp[i], dp[j] + 1);}}ret = Math.max(dp[i], ret);}return ret;}
}
2.4 题四:猜数字大小II
. - 力扣(LeetCode)
2.4.1 算法原理
暴力枚举出所有可能出现的情况,选出花费最小的最佳策略。
- 每一种情况都需要选出左右子树中话费金额的最大值(保证能赢)
- 每种情况话费的金额为:max(左,右)+本身
- 选出所有情况中花费最小的最佳策略。
2.4.2 算法代码
class Solution {int[][] memo;public int getMoneyAmount(int n) {memo = new int[n + 1][n + 1];return dfs(1, n);}public int dfs(int s, int e) {int ret = Integer.MAX_VALUE;if(s >= e) {return 0;}if(memo[s][e] != 0) return memo[s][e];for(int i = s; i <= e; i++) {int left = dfs(s, i - 1);int right = dfs(i + 1, e);ret = Math.min(Math.max(left, right) + i, ret);}memo[s][e] = ret;return ret;}
}
2.5 题五:矩阵中的最长递增路径【困难】
. - 力扣(LeetCode)
2.5.1 算法原理
- 枚举所有节点,选出所有节点中最长的路径
- 函数设计:dfs(i,j) --> 返回(i,j)位置的最长路径
- 一个位置的最长路径是固定的 --> 备忘录int[][] memo
2.5.2 算法代码
class Solution {int m, n;int[] dx = {1, -1, 0, 0};int[] dy = {0, 0, 1, -1};int[][] matrix;int[][] memo;//备忘录public int longestIncreasingPath(int[][] matrix_) {matrix = matrix_;m = matrix.length; n = matrix[0].length;memo = new int[m + 1][n + 1];int ret = 0;for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {ret = Math.max(ret, dfs(i, j));}}return ret;}public int dfs(int i, int j) {if(memo[i][j] != 0) return memo[i][j];int ret = 1;for(int k = 0; k < 4; k++) {int x = i + dx[k];int y = j + dy[k];if(x >= 0 && x < m && y >= 0 && y < n && matrix[x][y] > matrix[i][j]) {//求出当前位置的最长路径ret = Math.max(ret, dfs(x, y) + 1);}}memo[i][j] = ret;return ret;}
}
END
相关文章:
记忆化搜索专题——算法简介力扣实战应用
目录 1、记忆化搜索算法简介 1.1 什么是记忆化搜索 1.2 如何实现记忆化搜索 1.3 记忆化搜索与动态规划的区别 2、算法应用【leetcode】 2.1 题一:斐波那契数 2.1.1 递归暴搜解法代码 2.1.2 记忆化搜索解法代码 2.1.3 动态规划解法代码 2.2 题二࿱…...
【Java】【力扣】83.删除排序链表中的重复元素
题目 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 示例 1: 输入:head [1,1,2] 输出:[1,2]示例 2: 输入:head [1,1,2,3,3] 输出&#…...
vue3项目实现全局国际化
本文主要梳理vue3项目实现全项目格式化,例如在我前面文章使用若依创建vue3的项目中,地址:若依搭建vue3项目在导航栏中切换,页面中所有的组件的默认语言随之切换,使用的组件库依旧是element-plus,搭配vue-i1…...
Oracle 19c异常恢复—ORA-01209/ORA-65088---惜分飞
由于raid卡bug故障,导致文件系统异常,从而使得数据库无法正常启动,客户找到我之前已经让多人分析,均未恢复成功,查看alert日志,发现他们恢复的时候尝试resetlogs库,然后报ORA-600 kcbzib_kcrsds_1错误 2024-09-15T17:07:32.55321508:00 alter database open resetlogs 2024-09-…...
【Webpack--000】了解Webpack
🤓😍Sam9029的CSDN博客主页:Sam9029的博客_CSDN博客-前端领域博主 🐱🐉若此文你认为写的不错,不要吝啬你的赞扬,求收藏,求评论,求一个大大的赞!👍* &#x…...
开源 AI 智能名片链动 2+1 模式 S2B2C 商城小程序与社交电商的崛起
摘要:本文深入探讨了社交电商迅速发展壮大的原因,并分析了开源 AI 智能名片链动 21 模式 S2B2C 商城小程序在社交电商中的重要作用。通过对传统电商与社交电商的对比,以及对各发展因素的剖析,阐述了该小程序如何为社交电商提供新的…...
在线IP代理检测:保护您的网络安全
在互联网飞速发展的今天,越来越多的人开始意识到网络安全和隐私保护的重要性。在线IP代理检测工具作为一种有效的网络安全手段,能够帮助用户识别和检测IP代理的使用情况,从而更好地保护个人隐私和数据安全。本文将详细介绍在线IP代理检测的相…...
【算法】BFS—解开密码锁的最少次数
题目 一个密码锁由 4 个环形拨轮组成,每个拨轮都有 10 个数字: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 。每个拨轮可以自由旋转:例如把 9 变为 0,0 变为 9 。每次旋转都只能旋转一个拨轮的一位数字。 锁的初始数字为 0000 ,一个…...
非守护线程会阻止JVM的终止吗
非守护线程会阻止JVM的终止。在Java中,线程分为守护线程(Daemon Threads)和非守护线程(Non-Daemon Threads,也被称为用户线程)。这两种线程在JVM终止时表现出不同的行为。 非守护线程是JVM中执行程序主要逻…...
Grafana面板-linux主机详情(使用标签过滤主机监控)
1. 采集器添加labels标签区分业务项目 targets添加labels (模板中使用的project标签) … targets: [‘xxxx:9100’] labels: project: app2targets: [‘xxxx:9100’] labels: project: app1 … 2. grafana面板套用 21902 模板 演示...
MYSQL数据库基础篇——DDL
DDL:DDL是数据定义语言,用来定义数据库对象。 一.DDL操作数据库 1.查询 ①查询所有数据库 输入; 得到结果: ②查询当前数据库 输入; 例如执行下面语句: 2.创建 输入 然后展示数据库即可得到结果&…...
Springboot 集成 Swing
背景 Springboot 在 Java 给 Java 开发带来了极大的便利,那么如何把它集成到 Swing GUI 编程项目中,使得 GUI 编程更加高效?本人简单做了一下尝试,完成一个 demo ,贴出来供大家参考 具体步骤 创建一个 spring boot …...
枚举算法总结
枚举算法(Enumeration Algorithm)是一种简单而直接的算法设计策略,它通过列出问题的所有可能情况,逐一进行验证,直到找到问题的解。这种算法适用于问题的解空间不是太大,可以通过遍历所有情况来找到答案的情…...
编译 Android 11源码
参考小米6 lineageos官方编译文档:https://wiki.lineageos.org/devices/sagit/build 单独编译 framework 以LineageOS18.1(Android 11)为例: 1、在源码根目录执行: make framework-minus-apex 2、用生成的framewo…...
时间复杂度计算 递归(solve2 后续)
原帖 最近校内比较忙,更新缓慢,致歉。 这里函数每次都需要遍历 h h h 和 m m m 之间的数(复杂度 O ( n ) O(n) O(n)),所以和 solve1 略有不同。仍然假设 T ( n ) \operatorname{T}(n) T(n) 表示 m − h 1 n…...
Nginx:高性能Web服务器与反向代理的深度剖析
Nginx:高性能Web服务器与反向代理的深度剖析 Nginx(发音为“engine X”)是一款轻量级但功能强大的Web服务器和反向代理服务器,以其高并发处理能力、低内存占用和灵活的扩展性在互联网项目中得到了广泛应用。本文将深入探讨Nginx…...
JavaSE - 面向对象编程03
01 多态 01_01 认识多态 01_02 多态的好处和缺点 【1】好处:① 可以解耦合,扩展性更强,父类引用指向的子类对象可以随时切换,而后面的逻辑代码并不需要更改。 ② 使用父类引用可以作为方法的形参或返回类型来接收一切子类对象。…...
变电站缺陷数据集8307张,带xml标注和txt标注,可以直接用于yolo训练
变电站缺陷数据集8307张, 带xml标注和txt标注,可以直接用于yolo训练,赠附五个脚本 变电站缺陷数据集 数据集概述 变电站缺陷数据集是一个专门针对变电站设备和环境缺陷检测的图像数据集。该数据集包含了8307张经过标注的图像,旨…...
Redis的存储原理和数据模型
一、Redis是单线程还是多线程呢? 我们通过跑redis的代码,查看运行的程序可以得知,Redis本身其实是个多线程,其中包括redis-server,bio_close_file,bio_aof_fsync,bio_lazy_free,io_t…...
Linux 文件与目录操作命令详解
文章目录 前言创建文件1. touch2. vim 文件内容显示3. cat4. more5. less6. head7. tail 文件(目录)复制、删除和移动8. cp9. rm10. mv 压缩文件与解压缩11. gzip12. zip 和 unzip 创建目录13. mkdir 删除目录14. rmdir 改变工作目录15. cd16. pwd 显示目…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
