算法:记忆化搜索

news2024/12/25 1:09:54

文章目录

  • 记忆化搜索
    • 斐波那契数列
  • 例题
    • 不同路径
    • 最长递增子序列
    • 猜数字大小
    • 矩阵中的最长递增路径

记忆化搜索的原理其实很简单,简单来说就是对暴力搜索的一些优化,因此整体上来讲难度不高

记忆化搜索

所谓记忆化搜索,直白来说就是一个带有备忘录的递归

如何实现记忆化搜索?

  1. 添加一个备忘录
  2. 递归每次返回的时候,都把结果放在备忘录当中
  3. 每次进行递归前,都到备忘录中看一看

下面用一个经典题目诠释记忆化搜索的意义

斐波那契数列

在这里插入图片描述

  1. 递归
class Solution 
{
public:
    // 递归
    int fib(int n) 
    {
        if(n == 0 || n == 1) return n;
        return fib(n - 1) + fib(n - 2);
    }
};
  1. 动态规划
class Solution 
{
public:
    // 动态规划
    int fib(int n) 
    {
        if(n == 0 || n == 1)
            return n;
        vector<int> v(n + 1);
        v[0] = 0, v[1] = 1;
        for(int i = 2; i <= n; i++)
            v[i] = v[i - 1] + v[i - 2];
        return v[n];
    }
};
  1. 记忆化搜索
class Solution 
{
public:
    // 记忆化搜索
    int memo[31];
    int fib(int n) 
    {
        // 先到备忘录中看看
        if(memo[n] != 0)
            return memo[n];
        if(n == 0 || n == 1)
        {
            memo[n] = n;
            return memo[n];
        }
        return fib(n - 1) + fib(n - 2);
    }
};

从上面这个例题能感觉出来,记忆化搜索其实就是在递归的基础上进行了一些优化,没有什么本质性的新增内容,基于这个原因,用下面的例题来进一步学习记忆化搜索

例题

不同路径

在这里插入图片描述
暴力搜索

class Solution 
{
public:

    int dfs(int m, int n, int p, int q)
    {
        if(m > p || n > q) return 0;
        if(m == p && n == q) return 1;
        return dfs(m + 1, n, p, q) + dfs(m, n + 1, p, q);
    }

    int uniquePaths(int m, int n) 
    {
        return dfs(0, 0, m - 1, n - 1);
    }
};

采用记忆化搜索进行一定程度的优化

class Solution 
{
public:
    int arr[101][101];
    int dfs(int m, int n, int p, int q)
    {
        if(arr[m][n] != 0) return arr[m][n];
        if(m > p || n > q) return 0;
        if(m == p && n == q) return 1;
        int down = dfs(m + 1, n, p, q);
        int right = dfs(m, n + 1, p, q);
        arr[m + 1][n] = down;
        arr[m][n + 1] = right;
        return down + right;
    }

    int uniquePaths(int m, int n) 
    {
        return dfs(0, 0, m - 1, n - 1);
    }
};

最长递增子序列

在这里插入图片描述

暴力搜索

class Solution
{
public:
	vector<int> path;
	int maxSize;
	int lengthOfLIS(vector<int>& nums)
	{
		dfs(0, nums, INT_MIN);
		return maxSize;
	}

	void dfs(int pos, vector<int>& nums, int prev)
	{
		maxSize = max(maxSize, (int)path.size());

		for (int i = pos; i < nums.size(); i++)
		{
			if (nums[i] > prev)
			{
				path.push_back(nums[i]);
				dfs(i + 1, nums, nums[i]);
				path.pop_back();
			}
		}
	}
};

记忆化搜索

class Solution 
{
public:
    int memo[2501];

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

    int dfs(int pos, vector<int>& nums)
    {
        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(i, nums) + 1);
            }
        }
        memo[pos] = ret;
        return ret;
    }
};

猜数字大小

在这里插入图片描述
暴力搜索

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

    int dfs(int begin, int end)
    {
        if(begin >= end) return 0;
        int res = INT_MAX;
        // 选一个节点作为根节点
        for(int i = begin; i <= end; i++)
        {
            // 找左子树花费的钱
            int left = i + dfs(begin, i - 1);
            // 找右子树花费的钱
            int right = i + dfs(i + 1, end);
            res = min(res, max(left, right));
        }
        return res;
    }
};

记忆化搜索优化

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

    int dfs(int begin, int end)
    {
        if(begin >= end) return 0;
        if(memo[begin][end] != 0) return memo[begin][end];
        int res = INT_MAX;
        // 选一个节点作为根节点
        for(int i = begin; i <= end; i++)
        {
            // 找左子树花费的钱
            int left = i + dfs(begin, i - 1);
            // 找右子树花费的钱
            int right = i + dfs(i + 1, end);
            res = min(res, max(left, right));
        }
        memo[begin][end] = res;
        return res;
    }
};

矩阵中的最长递增路径

在这里插入图片描述
记忆化搜索

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

    // 从第i行和第j列的这个元素开始的最长递增路径
    int dfs(int i, int j, vector<vector<int>>& matrix)
    {
        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, 1 + dfs(x, y, matrix));
            }
        }
        memo[i][j] = ret;
        return ret;
    }
};

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

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

相关文章

MATLAB中plotmatrix函数用法

目录 语法 说明 示例 使用两个矩阵输入创建散点图矩阵 使用一个矩阵输入创建散点图矩阵 指定标记类型和颜色 创建并修改散点图矩阵 plotmatrix函数的功能是创建散点图矩阵。 语法 plotmatrix(X,Y) plotmatrix(X) plotmatrix(___,LineSpec) plotmatrix(ax,___) [S,AX,B…

一次显著的接口性能优化,从10s优化到0.9s

最近在登录项目后台的时候&#xff0c;发现当我输入账号和密码后&#xff0c;竟然就卡在了 Loading 页面。。 加载了10S才进后台 等了足足 10S 才进去后台&#xff01; 通过 F12&#xff0c;打开 Network 网络请求一看&#xff0c;竟然是因为有两个接口返回的数据太慢了&#…

挑战单芯片NOA,这款“All in one”方案或将改变主流市场走向

随着降本增效、电子架构升级&#xff08;尤其是跨域计算、多域融合等概念&#xff09;以及供应链减复&#xff08;降低电子物料的SKU&#xff09;的需求愈加明确&#xff0c;对于车载计算赛道&#xff0c;也带来新的变化。 比如&#xff0c;去年9月&#xff0c;英伟达率先发布下…

群晖邮件设置,错误535 Authenticate failed问题

设置邮件通知或者报警很方便&#xff0c;群晖内部内置这个功能。在设置的时候遇到错误535 Error&#xff1a;authentication failed。 原因是&#xff1a;这个错误就是认证失败&#xff01; 但是相信很多的同学明明用户名和密码填的是对的&#xff0c;就是说认证失败&#xf…

RTLS 颠覆制造业方式之——库存管理

跟踪库存对于每个行业&#xff08;不仅仅是制造业&#xff09;来说都是一项技术挑战。然而&#xff0c;在计划外停机每小时可能造成数十万美元损失的环境中&#xff0c;智能库存尤其重要&#xff0c;而这通常是由于一两个物体丢失造成的。 1.自动化库存报告 RTLS 提供的最有价…

[HTML]Web前端开发技术1,meta,HBuilder等——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;大大会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

九. Linux网络命令

网络命令write 网络命令wall 网络命令ping 首先&#xff0c;ping程序会向域名服务器(DNS)发送请求&#xff0c;解析域名www.baidu.com的IP地址。DNS返回域名的一个别名www.a.shifen.com以及对应的IP地址183.2.172.185。之后ping程序开始向这个地址发送请求报文&#xff0c;每1s…

浅谈霍尔电流传感器在UPS蓄电池浮充电流远程监测方案的应用-安科瑞 蒋静

摘要&#xff1a;针对无人平台UPS蓄电池多次出现浮充电流过高的现象&#xff0c;介绍了UPS系统的结构和工作原理&#xff0c;通过应用霍尔电流传感器&#xff0c;DCS组态&#xff0c;实现UPS蓄电池浮充电流远程监控&#xff0c;异常电流故障报警&#xff0c;推动了无人平台的自…

IO流-数据流

一&#xff0c;IO流-数据流 二&#xff0c;数据输出流 三&#xff0c;案例 package BigDecimal;import java.io.DataOutputStream; import java.io.FileOutputStream;public class DATaOutputStreamss {public static void main(String[] args) {try ( //1,创建一个数据输出流…

linuxTcp状态转换

1.TCP状态转换 在TCP进行三次握手&#xff0c;或者四次挥手的过程中&#xff0c;通信的服务器和客户端内部会发送状态上的变化&#xff0c;发生的状态变化在程序中是看不到的&#xff0c;这个状态的变化也不需要程序猿去维护&#xff0c;但是在某些情况下进行程序的调试会去查…

YB203H系列是一组CMOS技术实现的三端低功耗高电压稳压器

概述: YB203H系列是一组CMOS技术实现的三端低功耗高电压稳压器。输出电流为200mA且允许的输入电压可高达80V。具有几个固定的输出电压&#xff0c;范围从2.1V到12.0V.CMOS技术可确保其具有低压降和低静态电流的特性。最高耐压100W.尽管主要为固定电压调节器而设计&#xff0c;…

Spring过滤器和拦截器的区别

&#x1f4d1;前言 本文主要Spring过滤器和拦截器的区别的问题&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日一句&#x…

【Linux】Linux进程间通信(三)

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【Linux】…

SMART PLC星三角延时启动功能块(梯形图FC)

这里我们介绍SMART PLC星三角延时启动功能块,SMART PLC的周期定时器功能块请参考下面文章链接: 周期定时器FB_Cycle_time(SCL+梯形图代码)-CSDN博客文章浏览阅读80次。博途PLC定时器指令使用详细介绍请参考下面文章链接:博途PLC IEC定时器编程应用(SCL语言)_scl定时器-CS…

机器学习第6天:线性回归模型正则化

文章目录 机器学习专栏 正则化介绍 岭回归 岭回归成本函数 核心代码 示例 Lasso回归 Lasso回归损失函数 核心代码 弹性网络 弹性网络成本函数 核心代码 结语 机器学习专栏 机器学习_Nowl的博客-CSDN博客 正则化介绍 作用&#xff1a;正则化是为了防止模型过拟合…

ESP32-0.96寸OLED通过低功耗蓝牙BLE通信显示出ESP32-BME280读取到的温湿度值

ESP32-0.96寸OLED通过低功耗蓝牙BLE通信显示出ESP32-BME280读取到的温湿度值 简介ESP32-BME280作为BLE Server手机作为BLE Client与ESP32-BME280 BLE Server通信ESP32-0.96寸OLED作为BLE Client与ESP32-BME280 BLE Server通信总结 简介 两个ESP32开发板&#xff0c;一个ESP32挂…

【Hello Go】Go语言复合类型

复合类型 分类指针基本操作new函数指针作为函数的参数 数组概述操作数据数组初始化数组比较在函数之间传递数组 slice概述切片的创建和初始化切片操作切片和底层数组关系内建函数appendcopy 切片作为函数传参 map概述创建和初始化常用操作赋值遍历 删除map作函数参数 结构体结构…

C语言青蛙爬井(ZZULIOJ1072:青蛙爬井)

题目描述 有一口深度为high米的水井&#xff0c;井底有一只青蛙&#xff0c;它每天白天能够沿井壁向上爬up米&#xff0c;夜里则顺井壁向下滑down米&#xff0c;若青蛙从某个早晨开始向外爬&#xff0c;对于任意指定的high、up和down值&#xff08;均为自然数&#xff09;&…

《rPPG》——(1)PyTorch——Windows环境配置

《rPPG》——&#xff08;1&#xff09;PyTorch——Windows环境配置 如何查看电脑是否已安装Python环境以及Python版本 anaconda对应python3.8的版本号是多少? 截止到我的知识截止日期&#xff08;2022年1月&#xff09;&#xff0c;Anaconda支持Python 3.8的版本号是Anacond…

【数字人】7、GeneFace++ | 使用声音和面部运动系数的关系作为 condition 来指导 NeRF 重建说话头

文章目录 一、背景二、相关工作2.1 唇形同步的 audio-to-motion2.2 真实人像渲染 三、方法3.1 对 GeneFace 的继承3.2 GeneFace 的结构3.2.1 Pitch-Aware Audio-to-Motion Transform3.2.2 Landmark Locally Linear Embedding3.2.3 Instant Motion-to-Video Rendering 四、效果 …