【递归、搜索与回溯】记忆化搜索

2024-06-17 13:04
文章标签 搜索 递归 记忆 回溯

本文主要是介绍【递归、搜索与回溯】记忆化搜索,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、经验总结

以斐波那契数为例引入今天的主角:记忆化搜索和动态规划

题目链接

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

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

//解法二:递归->记忆化搜索
class Solution {int mem[31]; //备忘录
public:Solution(){memset(mem, -1, sizeof(mem));}int fib(int n) {if(mem[n] != -1) return mem[n];if(n==0 || n==1) mem[n] = n;     elsemem[n] = fib(n-1) + fib(n-2);return mem[n];}
};//解法三:动态规划
class Solution {int dp[31]; //dp[i]表示第i个斐波那契数
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.1 不同路径

题目链接

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

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

动态规划:从(1, 1)位置走起,到(m, n)位置结束。将第0行,第0列空下初始化为0方便处理边界情况。

编写代码

//解法一:记忆化搜索——自顶向下
class Solution {
public:int uniquePaths(int m, int n) {vector<vector<int>> memo(m+1, vector<int>(n+1, 0));return dfs(m, n, memo);}int dfs(int m, int n, vector<vector<int>>& memo){if(m<1 || n<1) return 0;if(m==1 && n==1) return 1;if(memo[m][n]!=0) return memo[m][n];memo[m][n] = dfs(m-1, n, memo)+dfs(m, n-1, memo);return memo[m][n];}
};//解法二:动态规划——自底向上
class Solution {
public:int uniquePaths(int m, int n) {vector<vector<int>> dp(m+1, vector<int>(n+1, 0));dp[1][1] = 1;for(int i = 1; i <= m; ++i){for(int j = 1; j <= n; ++j){if(i==1 && j==1) continue;else dp[i][j] = dp[i-1][j]+dp[i][j-1];}}return dp[m][n];}
};

2.2 最长递增子序列

题目链接

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

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

//解法一:记忆化搜索——自顶向下
class Solution {int n;
public:int lengthOfLIS(vector<int>& nums) {n = nums.size();vector<int> memo(n, 0); //记录的是每个位置对应的最长递增子序列int ret = 1;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; //这里一定要初始化为1,最后一个元素不进入循环直接返回1for(int i = pos+1; i < n; ++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();vector<int> dp(n, 1);dp[n-1] = 1; //初始化:最后一个位置的长度为1int ret = 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.3 猜数字大小Ⅱ

题目链接

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

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:int getMoneyAmount(int n) {vector<vector<int>> memo(n+1, vector<int>(n+1, 0)); //memo记录的是i位置的最小现金return DFS(1, n, memo); //DFS返回的是确保获胜的最小现金数}int DFS(int l, int r, vector<vector<int>>& memo){if(l >= r) return 0; //l>r区间不存在;l==r区间内只有一个元素,一次选中不需要付钱if(memo[l][r] != 0) return memo[l][r];int ret = INT_MAX;for(int i = l; i <= r; ++i){int left = DFS(l, i-1, memo); //左区间int right = DFS(i+1, r, memo); //右区间int tmp = max(left, right)+i; //确保获胜取maxret = min(ret, tmp); //最小现金数取min}memo[l][r] = ret;return ret;}
};

2.4 矩阵中的最长递增路径

题目链接

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

题目描述

在这里插入图片描述

算法原理

见代码

编写代码

class Solution {int dx[4] = {0, 0, 1, -1};int dy[4] = {1, -1, 0, 0};int m, n;
public:int longestIncreasingPath(vector<vector<int>>& matrix) {m = matrix.size(), n = matrix[0].size();vector<vector<int>> memo(m, vector<int>(n, 0));int ret = 0;// 选择路径起点for(int i = 0; i < m; ++i){for(int j = 0; j < n; ++j){ret = max(DFS(matrix, i, j, memo), ret); //DFS暴搜+memo优化}}return ret;}int DFS(vector<vector<int>>& matrix, int r, int c, vector<vector<int>>& memo){if(memo[r][c] != 0) return memo[r][c];int ret = 1;for(int i = 0; i < 4; ++i){int x = r+dx[i], y = c+dy[i];if(x>=0 && x<m && y>=0 && y<n && matrix[x][y]>matrix[r][c]){ret = max(DFS(matrix, x, y, memo)+1, ret);}}memo[r][c] = ret;return ret;}
};

这篇关于【递归、搜索与回溯】记忆化搜索的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1069517

相关文章

HTML5 搜索框Search Box详解

《HTML5搜索框SearchBox详解》HTML5的搜索框是一个强大的工具,能够有效提升用户体验,通过结合自动补全功能和适当的样式,可以创建出既美观又实用的搜索界面,这篇文章给大家介绍HTML5... html5 搜索框(Search Box)详解搜索框是一个用于输入查询内容的控件,通常用于网站或应用程

mysql递归查询语法WITH RECURSIVE的使用

《mysql递归查询语法WITHRECURSIVE的使用》本文主要介绍了mysql递归查询语法WITHRECURSIVE的使用,WITHRECURSIVE用于执行递归查询,特别适合处理层级结构或递归... 目录基本语法结构:关键部分解析:递归查询的工作流程:示例:员工与经理的层级关系解释:示例:树形结构的数

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Jackson库进行JSON 序列化时遇到了无限递归(Infinite Recursion)的问题及解决方案

《Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursion)的问题及解决方案》使用Jackson库进行JSON序列化时遇到了无限递归(InfiniteRecursi... 目录解决方案‌1. 使用 @jsonIgnore 忽略一个方向的引用2. 使用 @JsonManagedR

Python使用DeepSeek进行联网搜索功能详解

《Python使用DeepSeek进行联网搜索功能详解》Python作为一种非常流行的编程语言,结合DeepSeek这一高性能的深度学习工具包,可以方便地处理各种深度学习任务,本文将介绍一下如何使用P... 目录一、环境准备与依赖安装二、DeepSeek简介三、联网搜索与数据集准备四、实践示例:图像分类1.

Rust中的BoxT之堆上的数据与递归类型详解

《Rust中的BoxT之堆上的数据与递归类型详解》本文介绍了Rust中的BoxT类型,包括其在堆与栈之间的内存分配,性能优势,以及如何利用BoxT来实现递归类型和处理大小未知类型,通过BoxT,Rus... 目录1. Box<T> 的基础知识1.1 堆与栈的分工1.2 性能优势2.1 递归类型的问题2.2

C# ComboBox下拉框实现搜索方式

《C#ComboBox下拉框实现搜索方式》文章介绍了如何在加载窗口时实现一个功能,并在ComboBox下拉框中添加键盘事件以实现搜索功能,由于数据不方便公开,作者表示理解并希望得到大家的指教... 目录C# ComboBox下拉框实现搜索步骤一步骤二步骤三总结C# ComboBox下拉框实现搜索步骤一这

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu 4517 floyd+记忆化搜索

题意: 有n(100)个景点,m(1000)条路,时间限制为t(300),起点s,终点e。 访问每个景点需要时间cost_i,每个景点的访问价值为value_i。 点与点之间行走需要花费的时间为g[ i ] [ j ] 。注意点间可能有多条边。 走到一个点时可以选择访问或者不访问,并且当前点的访问价值应该严格大于前一个访问的点。 现在求,从起点出发,到达终点,在时间限制内,能得到的最大