当前位置: 首页 > 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.…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...