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

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

相关文章

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

【文末附gpt升级秘笈】腾讯元宝AI搜索解析能力升级:千万字超长文处理的新里程碑

腾讯元宝AI搜索解析能力升级:千万字超长文处理的新里程碑 一、引言 随着人工智能技术的飞速发展,自然语言处理(NLP)和机器学习(ML)在各行各业的应用日益广泛。其中,AI搜索解析能力作为信息检索和知识抽取的核心技术,受到了广泛的关注和研究。腾讯作为互联网行业的领军企业,其在AI领域的探索和创新一直走在前列。近日,腾讯旗下的AI大模型应用——腾讯元宝,迎来了1.1.7版本的升级,新版本在AI搜

算法与数据结构面试宝典——回溯算法详解(C#,C++)

文章目录 1. 回溯算法的定义及应用场景2. 回溯算法的基本思想3. 递推关系式与回溯算法的建立4. 状态转移方法5. 边界条件与结束条件6. 算法的具体实现过程7. 回溯算法在C#,C++中的实际应用案例C#示例C++示例 8. 总结回溯算法的主要特点与应用价值 回溯算法是一种通过尝试各种可能的组合来找到所有解的算法。这种算法通常用于解决组合问题,如排列、组合、棋盘游

C++ 重建二叉树(递归方法)

/*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* };*/#include <vector>class Solution {public:/*** 代码

代码随想录算法训练营第三十九天|62.不同路径 63. 不同路径 II 343.整数拆分 96.不同的二叉搜索树

LeetCode 62.不同路径 题目链接:62.不同路径 踩坑:二维的vector数组需要初始化,否则会报错访问空指针 思路: 确定动态数组的含义:dp[i][j]:到达(i,j)有多少条路经递推公式:dp[i][j] = dp[i-1][j] + dp[i][j-1]初始化动态数组:dp[0][0] = 1遍历顺序:从左到右,从上到下 代码: class Solution {pu

大学生自救数据结构与算法(py实现)——01递归

目录 目录 递归 基本概念 工作原理 基本要素 优点 缺点 实现技巧 实例解析:计算阶乘 斐波那契数列 高效的斐波那契数列 python中的最大递归深度 二分查找 基本原理 性能分析 优化与变体 线性递归  元素序列的递归求和 二路递归 二路递归的基本概念 典型应用 工作原理 多重递归  示例:计算卡特兰数(Catalan Number) 尾递

leetcode刷题(45)——35. 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” 例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5] 示例 1: 输入: root = [

【智能优化算法改进策略之局部搜索算子(五)—自适应Rosenbrock坐标轮换法】

1、原理介绍 作为一种有效的直接搜索技术,Rosenbrock坐标轮换法[1,2]是根据Rosenbrock著名的“香蕉函数”的特点量身定制的,该函数的最小值位于曲线狭窄的山谷中。此外,该方法是一种典型的基于自适应搜索方向集的无导数局部搜索技术。此法于1960年由Rosenbrock提出,它与Hooke-Jeeves模式搜索法有些类似,但比模式搜索更为有效。每次迭代运算分为两部分[3]: 1)

对递归执行过程的简单描述

1. 分析代码 #include <stdio.h>void fun(int n){printf("1th - Level: %d Address: %d\n", n, &n);if(n < 3)fun(n+1);printf("2th - Level: %d Address: %d\n", n, &n);}int main(){fun(1);return 0;} 输出结果为:

Day59 代码随想录打卡|二叉树篇---把二叉搜索树转换为累加树

题目(leecode T538): 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下,二叉搜索树满足下列约束条件: 节点的左子树仅包含键 小于 节点键的节点。节点的右子树仅包含键 大于 节点键的节点。左右子树也必须是二叉搜索树。 方法:本题