如何让算法拥有“记忆”?一文读懂记忆化搜索

news2024/10/8 13:59:21

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

文章目录

目录

文章目录

前言

一  什么是记忆化搜索

二  相关题目练习

2.1  斐波那契数(详解记忆化搜索)

​编辑 解法一(递归):

解法二(记忆化搜索):

解法三(动态规划): 

2.2  不同路径 

 2.3  最长递增子序列

 2.4  猜数字大小II

2.5   矩阵中的最长递增路径

总结


前言

本篇详细介绍了进一步介绍记忆化搜索,让使用者对记忆化搜素有更加深刻的认知,而不是仅仅停留在表面,更好的模拟,为了更好的使用. 文章可能出现错误,如有请在评论区指正,让我们一起交流,共同进步!


一  什么是记忆化搜索

记忆化搜索(Memoization Search):是一种通过存储已经遍历过的状态信息,从而避免对同一状态重复遍历的搜索算法。

        记忆化搜索是动态规划的一种实现方式。在记忆化搜索中,当算法需要计算某个子问题的结果时,它首先检查是否已经计算过该问题。如果已经计算过,则直接返回已经存储的结果;否则,计算该问题,并将结果存储下来以备将来使用。  

        这样看概念可能有些抽象,接下来将用斐波那契数作为例子讲解 

二  相关题目练习

2.1  斐波那契数(详解记忆化搜索)

509. 斐波那契数 - 力扣(LeetCode)

 解法一(递归):

class Solution {
public:
    int fib(int n) {
        return dfs(n);
    }

    int dfs(int n)
    {
        if(n == 0 || n == 1)    return n;
        return dfs(n-1) + dfs(n-2);
    }
};

 从解法上看,这是一种低效的做法,时间复杂度为(2的n次方),那么为什么呢?

 我们发现,递归的解法重复计算,导致效率低下!

那么我们可不可以用一个备忘录记录下重复计算的值呢?

解法二(记忆化搜索):

class Solution {
    int memo[31];  //memory
public:
    int fib(int n) {
        memset(memo,-1,sizeof(memo));
        return dfs(n);
    }

    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];
    }
};

解法三(动态规划): 

class Solution {
    int dp[31];
public:
    int fib(int n) {
        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  不同路径 

62. 不同路径 - 力扣(LeetCode)

 

解法一:记忆化搜索

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> memo(m+1,vector<int>(n+1));
        return dfs(m,n,memo);
    }

    int dfs(int i,int j,vector<vector<int>>& memo)
    {
        if(memo[i][j] != 0)
        {
            return memo[i][j];
        }
        if(i == 0 || j == 0)    return 0;
        if(i == 1 && j == 1)
        {
            memo[i][j] = 1;
            return 1;
        }

        memo[i][j] = dfs(i,j-1,memo) + dfs(i-1,j,memo);
        return memo[i][j];
    }
};

解法二:动态规划 

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];
    }
};

 2.3  最长递增子序列

300. 最长递增子序列 - 力扣(LeetCode)

 

解法一:记忆化搜索

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        vector<int> memo(n);
        int ret = 0;
        for(int i = 0;i < n;i++)
            ret = max(ret,dfs(nums,i,memo));
        return ret;
    }

    int dfs(vector<int>& nums,int pos,vector<int>& memo)
    {
        if(memo[pos] != 0)  return memo[pos];
        int ret = 1;
        for(int i = pos + 1; i < nums.size(); i++)
        {
            if(nums[i] > nums[pos])
            {
                ret = max(ret,dfs(nums,i,memo) + 1);
            }
        }
        memo[pos] = ret;
        return ret;
    }
};

解法二:动态规划 

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

 2.4  猜数字大小II

375. 猜数字大小 II - 力扣(LeetCode)

 

暴搜(超时):

class Solution {
public:
    int getMoneyAmount(int n) {
        return dfs(1,n);
    }

    int dfs(int left,int right)
    {
        if(left >= right)   return 0;

        int ret = INT_MAX;
        for(int head = left; head <= right; head++)
        {
            int x = dfs(left,head-1);
            int y = dfs(head+1,right);
            ret = min(ret,head+max(x,y));
        }
        return ret;
    }
};

记忆化搜索:

class Solution {
    int memo[201][201];
public:
    int getMoneyAmount(int n) {
        return dfs(1,n);
    }

    int dfs(int left,int right)
    {
        if(left >= right)   return 0;

        if(memo[left][right] != 0)  return memo[left][right];
        int ret = INT_MAX;
        for(int head = left; head <= right; head++)
        {
            int x = dfs(left,head-1);
            int y = dfs(head+1,right);
            ret = min(ret,head+max(x,y));
        }
        memo[left][right] = ret;
        return ret;
    }
};

2.5   矩阵中的最长递增路径

329. 矩阵中的最长递增路径 - 力扣(LeetCode)

 

class Solution {
    int m,n;
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    int memo[201][201];
public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        int ret = 0;
        m = matrix.size(),n = matrix[0].size();
        for(int i = 0;i<m;i++)
        {
            for(int j = 0;j<n;j++)
            {
                ret = max(ret,dfs(matrix,i,j));
            }
        }
        return ret;
    }

    int dfs(vector<vector<int>>& matrix,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], y = j + dy[k];
            if(x >=0 && x < m && y >= 0 && y < n && matrix[x][y] > matrix[i][j])
            {
                ret = max(ret,dfs(matrix,x,y)+1);
            }
        }
        memo[i][j] = ret;
        return ret;
    }
};


总结

✨✨✨各位读友,本篇分享到内容是否更好的让你理解记忆化搜索,如果对你有帮助给个👍赞鼓励一下吧!!
🎉🎉🎉世上没有绝望的处境,只有对处境绝望的人。
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!

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

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

相关文章

全面整理人工智能(AI)学习路线图及资源推荐,非常详细收藏我这一篇就够了

在人工智能&#xff08;AI&#xff09;飞速发展的今天&#xff0c;掌握AI技术已经成为了许多高校研究者和职场人士的必备技能。从深度学习到强化学习&#xff0c;从大模型训练到实际应用&#xff0c;AI技术的广度和深度不断拓展。作为一名AI学习者&#xff0c;面对浩瀚的知识海…

kafka的成神秘籍(java)

kafka的成神秘籍 kafka的简介 ​ Kafka 最初是由Linkedin 即领英公司基于Scala和 Java语言开发的分布式消息发布-订阅系统&#xff0c;现已捐献给Apache软件基金会。Kafka 最被广为人知的是作为一个 消息队列(mq)系统存在&#xff0c;而事实上kafka已然成为一个流行的分布式流…

【吊打面试官系列-MySQL面试题】试述视图的优点?

大家好&#xff0c;我是锋哥。今天分享关于【试述视图的优点&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 试述视图的优点&#xff1f; (1) 视图能够简化用户的操作 (2) 视图使用户能以多种角度看待同一数据&#xff1b; (3) 视图为数据库提供了一定程度的…

8年JAVA逆袭转AI之路!成功拿下offer

前段时间有一个粉丝投稿&#xff0c;他是8年老Java程序员了&#xff0c;每天两小时的碎片化学习时间&#xff0c;不仅没有陷入程序员的年龄恐慌&#xff0c;还拿到了目前薪资翻倍的offer 问到他是什么让他坚持学了6个月&#xff0c;他用了华为总裁任正非说的“今后职场上只有…

Nginx03-使用

零、文章目录 Nginx03-使用 1、Nginx服务器启停命令 对于 Nginx 的启停在 Linux 系统中也有很多种方式&#xff0c;我们介绍两种方式&#xff1a; Nginx信号控制Nginx命令行控制 &#xff08;1&#xff09;Nginx信号控制 查看Nginx 中的 master 和 worker 进程 [rootloc…

计算机进制之间的关系

计算机中常见的进制 十进制、二进制、十六进制、八进制之间对照表 进制之间的转换 通过上面的十进制对应二进制进位的表示&#xff1a; 当二进制产生增加位数时&#xff0c;相对应十进制数为2、4、8、16、32、64、128&#xff0c;也被称为二进制的位权&#xff0c;根据规律可知…

linux中缓存,在kafka上应用总结

linux中的缓存 页缓存 pagecatch&#xff08;读缓存用于提供快速读&#xff09;块缓存&#xff08;用于提供其他设备快速写&#xff09;当对读缓存读的时候&#xff0c;修改了读的数据&#xff0c;页缓存就会被标记为脏数据&#xff0c;等到写的时候它会向块缓存同步数据&…

关于7zip解压缩的下载和使用

我们有的时候下载软件&#xff0c;后缀是 ".exe" 或者 “.zip”&#xff0c;".7z"等&#xff0c;".exe"文件还好&#xff0c;打开就能进行下载&#xff0c;但是“.zip”&#xff0c;".7z“等就需要用解压缩软件进行解压了。 今天介绍的解…

No.11 笔记 | PHP学习指南:从函数到面向对象概览

一、PHP函数&#xff1a;代码复用的艺术 1. 函数的本质与魅力 函数是PHP的核心力量&#xff0c;分为内置函数和自定义函数函数名应当简洁明了&#xff0c;以字母或下划线开头 2. 函数的构成要素 function 关键字&#xff1a;函数的开始标志函数名&#xff1a;您的函数的独特…

【Git原理与使用】远程操作标签管理

远程操作&&标签管理 1.理解分布式版本控制系统2.新建远程仓库3.克隆远程仓库4.向远程仓库推送5.拉取远程仓库6.配置 Git7.配置命令别名8.标签管理8.1创建标签8.2操作标签 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496;…

把当抠门程序员,遇到了免费AI大模型

这篇想和大家分享一下&#xff0c;一个抠门的程序员和一个免费的AI大模型的故事。 “抠门程序员<–>免费大模型”&#xff0c;让我看看&#xff0c;能不能擦出马内的火花。 故事的开始 不知道有没有程序员和我一样&#xff0c;付费的东西&#xff0c;都会省着点开。什…

远程访问服务是什么?如何通过节点小宝远程访问办公室电脑?

在家办公若能各安其位、高效完成任务&#xff0c;实为美事。然而&#xff0c;现实往往不尽如人意&#xff0c;偶尔需用到办公室电脑上的资料&#xff0c;这时便需依赖远程访问服务的助力。那么&#xff0c;远程访问服务究竟是何方神圣&#xff1f;又该如何借助节点小宝实现对办…

解锁空间距离计算的多种方式-含前端、空间数据库、后端

目录 前言 一、空间数据库求解 1、PostGIS实现 二、GIS前端组件求解 1、Leaflet.js距离测算 2、Turf.js前端计算 三、后台距离计算生成 1、欧式距离 2、Haversice球面距离 3、GeoTools距离计算 4、Gdal距离生成 5、geodesy距离计算 四、成果与生成对比 1、Java不…

CSRF | POST 型 CSRF 漏洞攻击

关注这个漏洞的其他相关笔记&#xff1a;CSRF 漏洞 - 学习手册-CSDN博客 0x01&#xff1a;POST 型 CSRF 漏洞攻击 —— 理论篇 POST 型 CSRF 漏洞是指攻击者通过构造恶意的 HTTP POST 请求&#xff0c;利用用户的登录状态&#xff0c;在用户不知情的情况下&#xff0c;诱使浏览…

Mythical Beings:Web3游戏如何平衡创造内容、关注度与实现盈利的不可能三角

Web3游戏自其诞生以来&#xff0c;以去中心化和独特的代币经济体系迅速引起关注。然而&#xff0c;如何在创造内容、吸引用户和实现盈利之间达到平衡&#xff0c;始终是Web3游戏面临的核心挑战。Mythical Beings作为一款Web3卡牌游戏&#xff0c;通过创新设计和独特机制&#x…

java集合框架都有哪些

Java集合框架&#xff08;Java Collections Framework&#xff09;是Java提供的一套设计良好的支持对一组对象进行操作的接口和类。这些接口和类定义了如何添加、删除、遍历和搜索集合中的元素。Java集合框架主要包括以下几个部分&#xff1a; 接口&#xff1a; Collection&…

昆虫分类与检测系统源码分享

昆虫分类与检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Visio…

成都睿明智科技有限公司抖音电商服务佼佼者

在当今这个数字化浪潮汹涌的时代&#xff0c;抖音电商以其独特的魅力迅速崛起&#xff0c;成为众多商家竞相追逐的新蓝海。而在这场电商盛宴中&#xff0c;专业的服务商如同灯塔一般&#xff0c;为迷茫的商家指引方向。今天&#xff0c;我们就来深入探讨一家备受瞩目的服务商—…

Qt-QSpacerItem布局相关控件(45)

目录 描述 属性 使用 控件小结 描述 使⽤布局管理器的时候,可能需要在控件之间,添加⼀段空⽩.就可以使⽤ QSpacerItem 来表⽰ 属性 width宽度height⾼度hData⽔平⽅向的 sizePolicy • QSizePolicy::Ignored : 忽略控件的尺⼨&#xff0c;不对布局产⽣影响。 • QSizePol…

业务封装与映射 -- FlexE

什么是FlexE FlexE&#xff08;灵活以太网技术&#xff0c;Flexible Ethernet&#xff09;是由OIF 定义的灵活以太客户端接口标准&#xff0c; 是承载网实现业务隔离和网络分片的一种接口技术&#xff0c;支持路由器和光传输设备之间的灵活以太网连接&#xff0c;实现接口侧业务…