记忆化搜索【上】

509. 斐波那契数

题目链接:斐波那契数

递归(暴搜)

斐波那契数列,最传统的解法,采用递归:

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

n = 4的时候,虽然不是满二叉树,但是高度有4层,时间复杂度可以理解为O(2n)。

image-20240831205231259

记忆化搜索

这里递归展开,就会发现,做了很多次重复的递归,在此基础上可以将其优化,将递归过的数字,放入“备忘录”,当再次要递归该数的时候,直接从备忘录来取即可,这就是所谓的记忆化搜索。

  1. 添加一个备忘录
  2. 递归返回时,将结果放入备忘录
  3. 进入递归时,检查备忘录是否有
class Solution {
public:int memo[31];int fib(int n){//-1不可能出现在备忘录当中, 设为初始值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];}
};

动态规划

动态规划,五步走:

  1. 确定状态表示(dfs函数的含义)
  2. 推导状态转移方程(dfs函数体)
  3. 初始化(dfs函数递归出口)
  4. 确定填表顺序(填写备忘录顺序)
  5. 确定返回值(主函数如何调用dfs)

这五步和上面的记忆化搜索能一一对应起来,因为它们本质都是一样的,都将已经计算的值存起来

class Solution {
public:int dp[31];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];}
};

62. 不同路径

题目链接:62. 不同路径 - 力扣(LeetCode)

递归(暴搜)

image-20240831214045538

交给dfs到达(i, j)有多少种方法,这题就是到达(m, n)有多少种方法,函数头即是:dfs(m, n)

假设要到达菱形这个位置,只需要知道到达两个绿圆圈有多少种方法即可,因为只有必须要通过这两个位置,即dfs(i-1, j) + dfs(i, j-1)

image-20240831214338853

将起点设置为(1, 1)更方便遍历,那么当i == 0 || j == 0的时候,无需递归;
(1, 1)为起点,也无需递归,即这两个就是出口。

class Solution {
public:int uniquePaths(int m, int n){return dfs(m, n);}int dfs(int i, int j){if(i == 0 || j == 0){return 0;}if(i == 1 && j == 1){return 1;}return dfs(i-1, j) + dfs(i, j-1);}
};

暴搜会超时

记忆化搜索

这里递归展开,也会出现很多重复的,所以可以将暴搜转换成记忆化搜索:

  1. 定义一个“备忘录”
  2. 递归前检查“备忘录”
  3. 返回之前将结果存入“备忘录”
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-1, j, memo) + dfs(i, j-1, 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];}
};

300. 最长递增子序列

题目链接:300. 最长递增子序列 - 力扣(LeetCode)

递归

直接暴力枚举所有递增子序列,然后选出里面最长的

image-20240902224954596

代码解释:

  • 不知道是哪个起点的子序列最长,一次for循环
  • 递归函数,以当前位置为头,寻找下一个位置的子序列,一次for循环
  • 无需设置出口处,因为有for循环,遍历结束自动出来了
class Solution {
public: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){//要算自己int ret = 1;for(int i = pos+1; i < nums.size(); i++){if(nums[i] > nums[pos]){ret = max(ret, dfs(i, nums) + 1);}}return ret;}
};

会超时,多叉树

记忆化搜索

上图可见,递归的时候,会出现重复元素的递归,所有可以采用记忆化搜索的方式

class Solution {
public:int lengthOfLIS(vector<int>& nums){int ret = 0;vector<int> memo(nums.size(), 0);for(int i = 0; i < nums.size(); i++){ret = max(ret, dfs(i, nums, memo));}return ret;}int dfs(int pos, vector<int>& nums, 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(i, nums, memo) + 1);}}memo[pos] = ret;return ret;}
};

动态规划

  • dp表的含义:以某个位置为起点的最长递增子序列的长度
  • pos位置的时候,依赖的是pos后面的值,所以填表顺序是从后往前填
  • 要算上自己,所以初始的值为1
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[j] > nums[i]){dp[i] = max(dp[i], dp[j]+1);}}ret = max(ret, dp[i]);}return ret;}
};

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据-114 Flink DataStreamAPI 程序输入源 自定义输入源 Rich并行源 RichParallelSourceFunction

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

linux 高级IO

IO等&#xff08;要进行io是要有条件的&#xff0c;要有数据或者有空间&#xff09;拷贝。高效体现在等待的时间所占比重越低越高效。 阻塞IO&#xff1a;数据没有就绪&#xff0c;read不返回。在内核将数据准备好之前, 系统调用会一直等待。所有的套接字, 默认都是阻塞方式。…

nginx容器映射配置文件后,启动一直报错提示:failed (13: Permission denied)的排查

问题现象&#xff1a; 使用harbor 的install.sh 创建docker-compose之后&#xff0c;出现nginx容器一直重启。 查看日志发现是&#xff1a;配置文件无权限。报错信息如下&#xff1a; Sep 2 16:43:13 172.28.0.1 nginx[1344]: 2024/09/02 08:43:13 [emerg] 1#0: open() “/e…

百度地图绘制电子围栏(包括移动端绘制操作)以及检测坐标是否在电子围栏内

由于本人在PC端仅使用了多边形绘制&#xff0c;但矩形跟多边形用法基本一样&#xff0c;圆形并未使用&#xff0c;如不符合读者需求也可以参考一下。 绘制后得到的数据可能不同&#xff0c;但绘制方法仅仅是传递的参数不同。 关于给坐标数组在地图绘制图形的效果在移动端部分包…

深度学习系列74:语音中的mel谱

1 mel谱介绍 一个人说一句话&#xff0c;其 waveform 可以很不一样&#xff0c;但是 spectrogram 基本上会相似&#xff0c;甚至有人可以通过 spectrogram 来判断说话的内容。语谱图的横坐标是时间&#xff0c;纵坐标是频率&#xff0c;坐标点值为语音数据能量。由于是采用二维…

# 利刃出鞘_Tomcat 核心原理解析(十一)-- WebSocket -- 1

利刃出鞘_Tomcat 核心原理解析&#xff08;十一&#xff09;-- Tomcat 附加功能 WebSocket – 1 一、Tomcat专题 - WebSocket - 介绍 1、Tomcat 附加功能&#xff1a;websocket 介绍 1&#xff09;websocket &#xff1a;是 HTML5 新增的协议&#xff0c;它的目的是在浏览器…

动态规划法-资源分配问题

动态规划法 - 资源分配问题 问题描述 把4个份额的资源分配给3个工程&#xff0c;给定利润表如下表所示&#xff0c;写出资源的最优分配方案的求解过程。 4份资源分配给3个工程的利润表 步骤一&#xff1a;求各个阶段不同分配份额时的最大利润及分配份额 目标 我们的目标是…

53 mysql pid 文件的创建

前言 接上一篇文章 mysql 启动过程中常见的相关报错信息 在 mysql 中文我们在 “service mysql start”, “service mysql stop” 经常会碰到 mysql.pid 相关的错误信息 比如 “The server quit without updating PID file” 我们这里来看一下 mysql 中 mysql.pid 文件的…

微积分复习笔记 Calculus Volume 1 - 1.3Trigonometric Functions

1.3 Trigonometric Functions - Calculus Volume 1 | OpenStax

自己开发完整项目一、登录功能-05(动态权限控制)

一、上节回顾 在上一节中&#xff0c;我们介绍了如何通过数据库查询用户的权限&#xff0c;并对方法级别的接口使用注解的方式进行权限控制&#xff0c;之后通过用户携带的tocken进行解析权限&#xff0c;判断是否可以访问。 具体步骤&#xff1a; 1.在查询用户信息的时候将用户…

map和set的封装

目录 一、红黑树的改造 1.1节点的定义 二、红黑树的迭代器 2.1用节点封装迭代器 2.2迭代器的实现 2.3map和set的迭代器 三、insert的返回值 3.1insert返回值的用处 3.2operator[ ]的实现 四、key不能修改的问题 封装map和set一般分为六步&#xff1a; 封装map和set …

MFC生成dll的区别

主要分三种&#xff1a; A. 动态链接库(dll) B.具有导出项的(dll)动态链接库 C.MFC动态链接库 对比项目&#xff1a;可以根据需要选择哪种dll方便 添加自定义导出功能Demo 1. 添加导出实现接口&#xff1a; A. 导出需要具有&#xff1a;__declspec(dllexport) B. 按照C语言…

Javascript LeeCode选题(汉诺塔求解)

LeeCode选题 汉诺塔递归求解move移动函数hanoi函数main方法测试代码&#xff1a;代码实现 汉诺塔递归求解 汉诺塔介绍&#xff1a; 汉诺塔的的图形&#xff08;从上到下1&#xff0c;2&#xff0c;3个&#xff09;实现&#xff1a; 这里我们可以看到因为必须要将第n个移动到…

Spring中基于redis stream 的消息队列实现方法

本文主要介绍了消息队列的概念性质和应用场景&#xff0c;介绍了kafka、rabbitMq常用消息队列中间件的应用模型及消息队列的实现方式&#xff0c;并实战了在Spring中基于redis stream 的消息队列实现方法。 一、消息队列 消息队列是一种进程间通信或者同一个进程中不同线程间的…

uni-app 获取当前位置的经纬度以及地址信息

文章目录 uni.getLocation(objc)获取经纬度和地址调试结果问题 uni-app 获取当前位置的经纬度以及地址信息 uni.getLocation(objc) uni-app官方文档定位API: uni.getLocation(OBJECT) uni.getLocation({type: wgs84,success: function (res) {console.log(当前位置的经度&…

【系统架构设计】嵌入式系统设计(1)

【系统架构设计】嵌入式系统设计&#xff08;1&#xff09; 嵌入式系统概论嵌入式系统的组成硬件嵌入式处理器总线存储器I/O 设备与接口 软件 嵌入式开发平台与调试环境交叉平台开发环境交叉编译环境调试 嵌入式系统概论 嵌入性、专用性、计算机系统是嵌入式系统的三个基本的核…

【话题讨论】VS Code:倍增编程动力,实现效率飞跃

目录 引言 一、详情介绍 功能特点 使用场景 提高工作效率 二、效率对比 2.1 高度可定制性与丰富的插件生态 2.2 智能的代码补全与导航 2.3 内置的调试器与版本控制集成 2.4 轻量级与跨平台 2.5 选择合适工具的重要性 2.6 实际案例或数据展示 三、未来趋势 3.1 编…

能见度监测站—实时监测道路能见度情况

型号&#xff1a;TH-NJD10】能见度监测站是一种专门用于自动观测和存储气象观测数据的设备&#xff0c;它通过高科技手段实时监测大气能见度的变化&#xff0c;为多个领域提供重要的数据支持。主要基于光在大气中的衰减规律。传感器系统中的发射器发出光线&#xff0c;照射到空…

shell编程--正则表达式

正则表达式 正则表达式都被置于两个正斜杠之间&#xff1b;如/l[oO]ve/ 示例 匹配数字的脚本&#xff0c;用户输入创建账号的数量 语法&#xff1a; [[ ^[0-9]$ ]] 表示必须输入数字 #!/bin/bashwhile : do read -p "输入数字&#xff1a;" numif [[ $num ~ ^[…

产品需求过程管理重要性

产品需求过程管理重要性 背景 以下都是真实事项经历回顾&#xff0c;在产品开发过程中&#xff0c;产品经理与研发团队之间的沟通至关重要。然而&#xff0c;沟通不畅或信息缺失常常导致需求无法准确传达&#xff0c;最终影响产品的成功。以下是一些常见的问题&#xff1a; 1.需…