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

【算法】记忆化搜索



快乐的流畅:个人主页


个人专栏:《算法神殿》《数据结构世界》《进击的C++》

远方有一堆篝火,在为久候之人燃烧!

文章目录

  • 引言
  • 一、不同路径
  • 二、最长递增子序列
  • 三、猜数字大小 ||
  • 四、矩阵中的最长递增路径
  • 总结

引言

记忆化搜索,本质上是dfs + 备忘录,优化相同问题的搜索,极大提高算法效率。同时,记忆化搜索和普通的动态规划实际上是一样的,记忆化搜索是递归的形式,而动态规划是递推(循环)的形式。

一、不同路径


细节:

  • 设置备忘录的时候扩大一圈,方便处理边界情况:mem.resize(m + 1, vector(n + 1))
  • 进入dfs递归,先看看备忘录是否存在该值,若存在则直接返回:if(mem[i][j] != 0) return mem[i][j]
  • dfs(i, j):表示到(i, j)位置的路径数量
  • dfs(i, j) = dfs(i - 1, j) + dfs(i, j - 1)
  • 初始化:
    • if(i == 0 || j == 0) return 0
    • if(i == 1 && j == 1) mem[i][j] = 1,return 1
  • 每次递归结束后,将结果存储在备忘录中:mem[i][j] = dfs(i, j - 1) + dfs(i - 1, j)

记忆化搜索版本

class Solution
{vector<vector<int>> mem;
public:int dfs(int i, int j){if(mem[i][j] != 0) return mem[i][j];if(i == 0 || j == 0) return 0;if(i == 1 && j == 1){mem[i][j] = 1;return 1;}mem[i][j] = dfs(i, j - 1) + dfs(i - 1, j);return mem[i][j];}int uniquePaths(int m, int n){mem.resize(m + 1, vector<int>(n + 1));return dfs(m, n);}
};

动态规划版本

class Solution
{
public:int uniquePaths(int m, int n){vector<vector<int>> dp(m + 1, vector<int>(n + 1));dp[1][1] = 1;for(int i=1; i<=m; ++i){for(int j=1; j<=n; ++j){if(i == 1 && j == 1) continue;dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[m][n];}
};

二、最长递增子序列


思路:

  • 进入dfs递归,先看看备忘录是否存在该值,若存在则直接返回:if(mem[pos] != 0) return mem[pos]
  • 递推关系式:(当前节点小于子节点时)当前节点的最大长度,是所有子节点中的最大长度 + 1
  • dfs函数:返回以pos开头的最长递增子序列的长度
  • 每次递归结束后,将结果存储在备忘录中:mem[pos] = len

记忆化搜索版本

class Solution
{vector<int> mem;int n;
public:int dfs(vector<int>& nums, int pos)//返回以pos开头的最长递增子序列的长度{if(mem[pos] != 0) return mem[pos];int len = 1;for(int i=pos+1; i<n; ++i){if(nums[pos] < nums[i]){len = max(len, dfs(nums, i) + 1);}}mem[pos] = len;return len;}int lengthOfLIS(vector<int>& nums){n = nums.size();mem.resize(n);int ret = 0;for(int i=0; i<n; ++i){ret = max(ret, dfs(nums, i));}return ret;}
};

动态规划版本

class Solution
{
public:int lengthOfLIS(vector<int>& nums){int n = nums.size();vector<int> dp(n, 1);int ret = 0;for(int i=n-1; i>=0; --i){for(int j=i+1; j<n; ++j){if(nums[i] < nums[j]){dp[i] = max(dp[i], dp[j] + 1);}}ret = max(ret, dp[i]);}return ret;}
};

注意:记忆化搜索改动态规划,与直接动态规划的填表顺序不一样。

三、猜数字大小 ||


思路:

  • 进入dfs递归,先看看备忘录是否存在该值,若存在则直接返回:if(mem[begin][end] != 0) return mem[begin][end]
  • dfs函数:返回给定区间中获胜的最小金额
  • 将begin到end这个大区间,分为两个区间
  • 取两个区间中的最大金额,加上节点本身的金额,更新结果,取所有结果的最小值返回
  • 每次递归结束后,将结果存储在备忘录中:mem[begin][end] = ret
class Solution
{int mem[201][201];
public:int dfs(int begin, int end){if(begin >= end) return 0;if(mem[begin][end] != 0) return mem[begin][end];int ret = INT_MAX;for(int i=begin; i<=end; ++i){int x = dfs(begin, i - 1), y = dfs(i + 1, end);ret = min(ret, i + max(x, y));}mem[begin][end] = ret;return ret;}int getMoneyAmount(int n){return dfs(1, n);}
};

四、矩阵中的最长递增路径


思路:

  • 进入dfs递归,先看看备忘录是否存在该值,若存在则直接返回:if(mem[i][j] != 0) return mem[i][j]
  • dfs函数:返回从(i, j)位置开始的最长递增路径的长度
  • 递推关系式:(当下一个搜索的位置大于当前位置时)当前最长路径长度,为所有下一位置的最长长度的最大值 + 1
  • 每次递归结束后,将结果存储在备忘录中:mem[i][j] = ret
class Solution
{int dx[4] = {1, -1, 0, 0};int dy[4] = {0, 0, 1, -1};int mem[201][201];int m, n;
public:int dfs(vector<vector<int>>& mat, int i, int j){if(mem[i][j] != 0) return mem[i][j];int ret = 1;for(int k=0; k<4; ++k){int x = i + dx[k], y = j + dy[k];if(x >= 0 && y >= 0 && x < m && y < n&& mat[x][y] > mat[i][j]){ret = max(ret, dfs(mat, x, y) + 1);}}mem[i][j] = ret;return ret;}int longestIncreasingPath(vector<vector<int>>& mat){m = mat.size(), n = mat[0].size();int ret = 0;for(int i=0; i<m; ++i){for(int j=0; j<n; ++j){ret = max(ret, dfs(mat, i, j));}}return ret;}
};

总结

记忆化搜索,主要难在递推关系式的推导,以及边界情况的把控,因为其本质就是动态规划。

当然,并不是所有题都很方便将记忆化搜索和动态规划相互转换,有些题写成记忆化搜索比较简单,有些题写成动态规划比较简单,因题而异


真诚点赞,手有余香

相关文章:

【算法】记忆化搜索

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、不同路径二、最长递增子序列三、猜数字大小 ||四、矩阵中的最长递增路径总结 引言 记忆化搜索&…...

博客系统多模块开发

创建工程 创建父工程 删除src目录&#xff0c;在pom.xml添加依赖&#xff1a; <!--统一版本 字符编码--><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.b…...

pdf阅读器哪个好用?五款PDF阅读器大比拼

pdf阅读器哪个好用&#xff1f;在数字化时代&#xff0c;PDF文档因其跨平台、跨设备的便捷性&#xff0c;已成为工作、学习和生活中不可或缺的一部分。而一款优秀的PDF阅读器&#xff0c;则能极大地提升我们处理PDF文档的效率与体验。今天&#xff0c;就让我们一起探索五款备受…...

C#实现Queue的加锁和解锁

在C#中&#xff0c;可以使用lock语句来对队列进行加锁和解锁&#xff0c;以确保在多线程环境下的线程安全。以下是一个简单的示例&#xff1a; using System; using System.Collections.Generic; using System.Threading;public class ThreadSafeQueue<T> {private read…...

北京邮电大学人工智能考数据结构,均分370!北京邮电大学计算机考研考情分析!

北京邮电大学&#xff08;Beijing University of Posts and Telecommunications&#xff09;&#xff0c;简称北邮&#xff0c;是中华人民共和国教育部直属、工业和信息化部共建的全国重点大学&#xff0c;位列国家“211工程”、“985工程优势学科创新平台”、“世界一流学科建…...

1. lambda初体验

首先声明一个函数式接口&#xff0c;就只接口内只有一个抽象方法 //函数式接口 public interface Factory {Object getObject();}接口实现类 public class SubClass implements Factory {Overridepublic Object getObject() {return new User();}}User类 public class User …...

C#之显示转换

在C#中显示转换分为三种本别是: 括号强转&#xff0c;parse法&#xff0c;convert法。下面就为大家介绍一下吧&#xff01;&#xff01;&#xff01; 括号强转 作用: 一般情况下 将高精度的类型转换为低精度 语法: 变量类型 变量名 (转换的变量类型名称) 变量&#xff1b; …...

汇编原理(三)编程

源程序&#xff1a; 汇编指令&#xff1a;有对应的机器码与其对应 伪指令&#xff1a;无对应的机器码&#xff0c;是由编译器来执行的指令&#xff0c;编译器根据伪指令来进行相关的编译工作。 ex1:XXX segment、XXX ends这两个是一对成对使用的伪指令&#xff0c;且必须会被用…...

[MySQL数据库] Java的JDBC编程(MySQL数据库基础操作完结)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …...

绿色瓶装水“暗战”竞争越发激烈,华润饮料谋上市同时多地扩产能

《港湾商业观察》黄懿 4月23日&#xff0c;纯净水牌“怡宝”母公司华润饮料&#xff08;控股&#xff09;有限公司&#xff08;下称“华润饮料”&#xff09;向港交所主板提交上市申请&#xff0c;联席保荐人为中银国际、中信证券、美银美林、瑞银集团。 在华润饮料递表不久之…...

C语言之指针详解(4)

文章目录 一、回调函数二、qsort使用举例2.1使用qsort函数排序整型数据2.2使用qsort函数排序结构体数据 三、qsort函数的模拟实现 一、回调函数 首先我们先来了解一下什么是回调函数 回调函数通俗来讲就是一个通过函数指针调用的函数。 如果你把函数的指针&#xff08;地址&am…...

0基础学习小红书博主IP特训营,37天 教你从小白到KOL(13节)

课程内容&#xff1a; 1 第一课:如何做好博主账号定位 .mp4 2 第一课作业,html 3 第二课:如何打造小红书爆款笔记(一)_.mp4 4 第二课:如何打造小红书爆款笔记(二).mp4 5 第二课作业,html 6 第三课:如何高效搭建选题库 .mp4 7 第三课作业,html 8 第四课:破解流量玄学&am…...

【openlayers系统学习】3.1-3.2彩色GeoTIFF图像渲染

一、彩色GeoTIFF图像渲染 Sentinel-2 卫星任务收集并传播覆盖地球陆地表面的图像&#xff0c;重访频率为 2 至 5 天。传感器收集多波段图像&#xff0c;其中每个波段都是电磁频谱的一部分。 2A 级 (L2A) 产品提供以下频段的表面反射率测量&#xff1a; BandDescriptionCentra…...

前端自动将 HTTP 请求升级为 HTTPS 请求

前端将HTTP请求升级为HTTPS请求有两种方式&#xff1a; 一、index.html 中插入meta 直接在首页 index.html 的 head 中加入一条 meta 即可&#xff0c;如下所示&#xff1a; <meta http-equiv"Content-Security-Policy" content"upgrade-insecure-requests&…...

辅助驾驶ADAS功能算法介绍

一、ADAS功能分类 按照行驶域划分,将ADAS功能分为行车功能、泊车功能和主动安全功能。 行车功能 ACC(Adaptive Cruise Control)自适应巡航控制TJA(Traffic Jam Assist)交通拥堵辅助LCC(Lane Centering Control)车道居中控制ICC(Integration Cruise Control)智能巡航系…...

Docker 安装kingbase V8r6

下载 官网下载&#xff0c;注意&#xff1a;这里下载 Docker 版本v8r6 安装 # 导入镜像 docker load -i kingbase.tar# 重命名 docker tag [image-name]:[tag] [new-image-name]:[new-tag]# 删除 docker rmi [image-name]:[tag]# 创建容器 docker run -tid \ --privileged \…...

Python 应用打包成 APK【全流程】

将 Python 应用打包成 APK。 文章目录 步骤 1: 安装 Buildozer 和其依赖Linux (Ubuntu) 环境下安装: 步骤 2: 创建你的 Python 应用步骤 3: 配置 Buildozer步骤 4: 打包成 APK总结 步骤 1: 安装 Buildozer 和其依赖 首先确保你的系统中已安装 Python 和 pip。接下来&#xff…...

jmeter之MD5加密接口请求教程

前言&#xff1a; 有时候在项目中&#xff0c;需要使用MD5加密的方法才可以登录&#xff0c;或者在某一个接口中遇到 登录获取token后才可以进行关联&#xff0c;下面介绍下遇到的常见使用 一、第一种方法&#xff1a;使用jmeter自带的函数助手digest 选择工具&#xff0c;选…...

R18 NTN中的RACH-less HO

在看R18 38.300时,发现NTN场景 增加了如下黄色字体的内容,R18 NTN支持了RACH-less HO,索性就简单看了看。 NTN RACH less HO相关的描述主要在38.331,38.213和38.321中。38.300中的描述显示:网络侧会通过RRCReconfiguration消息将RACH-less HO相关的配置下发给UE, 其中会包…...

QT使用gsoap获取手机归属地

1-环境变量 用的win32 E:\hes_scc\tools\gsoap_2.8.134\gsoap-2.8\gsoap\bin\win32 2-生成代码接口 自己建一个目录&#xff0c;在此打开cmd窗口&#xff0c;生成的文件都会在这个文件夹中。 这里用的手机归宿地。 wsdl2h -o GetPhoneInfo.h -s -n Phone -t ....\typemap.…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...