我看了答案还是有些不能完全理解,于是又去b站翻了翻教程基础DP,其中提到记忆化的递归(也称记忆化搜索),相当于结合了dp和递归的优点(这时我又觉得比DP还厉害),然后就准备写写记忆化递归。 ---- 目录 1.记忆化递归的解释与分析 2.记忆化递归的应用 ---- 一、记忆化递归的解释与分析 前面说道它结合了dp和递归的优点,分别是记忆化和逻辑清晰易懂。 记忆化递归则更加”投机取巧“了,它只计算了需要用的值并储存起来,而其它不会用到的值不去计算,最大化地减少了计算。 打个比方,dp就相当于计算了一个方阵上所有的点(无论有没有利用价值),而记忆化递归相当于计算了方阵上有价值的点,因此记忆化递归的运行时间可能比dp还要短。 (注意只是可能,因为斐波那契数列无论是dp还是记忆化递归,都是要把前面的值全部算出来的) ---- 二、记忆化递归的应用 感觉没啥写的,就拿分配宝藏来写shui一写shui吧。题目在这里。
一:简介 (1)记忆化搜索 即 搜索+动态规划数组记录上一层计算结果,避免过多的重复计算 算法上依然是搜索的流程,但是搜索到的一些解用动态规划的那种思想和模式作一些保存;一般说来,动态规划总要遍历所有的状态 可以归纳为:记忆化搜索=搜索的形式+动态规划的思想 (2)简单例子 题目描述:已知n个slots,1<n<17,每个slot有一个height,height的值有四种,分别为{1,2,3,4}. 搜索相对于动态规划最大的劣势无非就是重复计算子结构,所以我们在搜索的过程中,对于每一个子结构只计算一次,之后保存到数组里,以后要用到的时候直接调用就可以了,这就是我要介绍的记忆化搜索。 记忆化搜索的实质是动态规划,效率也和动态规划接近,形式是搜索,简单直观,代码也容易编写,不需要进行什么拓扑排序了。 可以采用记忆化搜索算法。
用一个公式简单地说:记忆化搜索=搜索的形式+动态规划的思想。 ,所以又称为记忆化搜索。 记忆化搜索递归式动态规划 1.记忆化搜索的思想 记忆化搜索的思想是,在搜索过程中,会有很多重复计算,如果我们能记录一些状态的答案,就可以减少重复搜索量 2、记忆化搜索的适用范围 根据记忆化搜索的思想 3、记忆化搜索的核心实现 a. 到此,就能明白,此题就是求出所有点与终点的最短距离,然后再从起点进行记忆化搜索。
一、记忆化搜索vs动态规划 . - 力扣(LeetCode) class Solution { public: //记忆化搜索 //1、设置一个备忘录,要确保备忘录初始化的结果不能跟我们实际计算的结果相同 } } }; 二、不同路径 class Solution { public: int uniquePaths(int m, int n) { //记忆化搜索 memo)+dfs(i,j-1,memo); return memo[i][j]; } }; 三、最长的递增子序列 class Solution { public: //记忆化搜索 //不用记忆化搜索的话会超时,因为本身就是一个多叉树 int lengthOfLIS(vector<int>& nums) { vector<int> memo 矩阵的最长递增路径 class Solution { public: int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int m,n; //记忆化搜索
论记忆化搜索 什么是记忆化搜索呢?搜索的低效在于没有能够很好地处理重叠子问题;动态规划虽然比较好地处理了重叠子问题,但是在有些拓扑关系比较复杂的题目面前,又显得无奈。 记忆化搜索正是在这样的情况下产生的,它采用搜索的形式和动态规划中递推的思想将这两种方法有机地综合在一起,扬长避短,简单实用,在信息学中有着重要的作用。 用一个公式简单地说:记忆化搜索=搜索的形式+动态规划的思想。 以上的定义是抄的,说的非常神奇。一开始啊,我也不理解。因为我是遇到某些题然后百度到的。经过学习,我发现,所谓记忆化搜索说白了就是暴力枚举。 只不过略微优雅一点,把算过的,有可能发生重复的部分进行记忆,不要发生重复计算即可。这就是所谓的记忆化搜索,这是我的理解。 在学习它的过程中,人们总要讲到什么是动态规划,讲到普通的搜索。 需要自己作出判断 * 最后在说:所谓记忆化搜索,就是暴力枚举。。。。。
之所以重复计算,是因为每一次尝试都是重新的开始,它并不知道这条路已经走过了,也就是没有记忆,所以我们引入一种优化的方法,就是记忆化搜索。 04 记忆化搜索 可以引入一个f[i][j]数组,记录以(i,j)为起点所能找到的最长路线的长度,初始赋值为-1,表示还没有走过。 ; } fout << maxHeight << endl; fin.close(); fout.close(); return 0; } 06 总结 记忆化搜索是一种非常实用的算法 ,因为深搜用递归很容易实现,记忆化又避免了重复子问题的计算,提高了运行效率。 这其实就是动态规划的思想,常见的动态规划用递推实现,相比记忆化搜索实现上会更难一点,而记忆化搜索就没有这个问题。 算法的适用场景也需要根据具体的问题来分析,一般常用在地图或者树型结构中。
记忆化搜索 什么是记忆化搜索呢? 记忆化搜索其实就是带了"备忘录"的递归,给递归加上一个"备忘录",递归每次返回的时候,将结果放到"备忘录"里面,在每次进入递归的时候,往"备忘录"里面看看,当前需要递归的数据时候在"备忘录"里存在,如果存在 下面我们看一道经典的递归题可以使用记忆化搜索优化: 1. 斐波那契数(记忆化搜索) 题目链接 -> Leetcode -509.斐波那契数(记忆化搜索) Leetcode -509.斐波那契数(记忆化搜索) 题目:斐波那契数 (通常用 F(n) 表示)形成的序列称为 不同路径Ⅱ(记忆化搜索) 题目链接 -> Leetcode -62.不同路径Ⅱ(记忆化搜索) Leetcode -62.不同路径Ⅱ(记忆化搜索) 题目:一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为
试着用记忆化搜索搞,调试了蛮长时间,终于搞定,这时当n为1000时便可在2s内得出答案,但时限1s,依旧超时,所以还可以进一步的优化。下面结合这道题总结下记忆化搜索。 记忆化搜索以搜索的形式加上动态规划的思想,面对会有很多重复计算的问题时,在搜索过程中记录一些状态的答案,可以减少重复搜索量。 记忆化搜索本质上是DP,它们都保存了中间结果,不同点是DP从下往上算,记忆化DFS因为是递归所以从上往下算。 记忆化搜索: 递归函数的结果以返回值形式存在,不能以全局变量或参数形式传递。 (根据以上两个要求把朴素暴搜dfs写出来后,添加个记忆化数组就ok了) 记忆化数组一般初始化为-1。在每一状态搜索的开始进行判断,如果该状态已经计算过,则直接返回答案,否则正常搜索。 如果对记忆化搜索不熟练,可以先写出void型dfs,再转化为有返回值的dfs,最后再加个数组记录已经搜过的状态就是记忆化dfs了。
概述 记忆化搜索算法事实上是一种对递归算法的优化 因为在递归算法中有很多重复计算,导致了非常离谱的时间和空间复杂度 所以我们采用记住计算结果的方式,能很大程度上减少复杂度 算法核心结构 此算法可以被抽象成为以下的结构 滑雪 十分典型的记忆化搜索题目,主要体现在if(f[x][y]!=-1) return f[x][y];上。 走方格 第十一届蓝桥杯省赛原题,除了记忆化搜索方法,还有正常dp方法可供选择。
概述 记忆化搜索是一种典型的空间换时间的思想。 记忆化搜索的典型应用场景是可能经过不同路径转移到相同状态的dfs问题。 更明确地说,当我们需要在有层次结构的图(不是树,即当前层的不同节点可能转移到下一层的相同节点)中自上而下地进行dfs搜索时,大概率我们都可以通过记忆化搜索的技巧降低时间复杂度。 (转移到没有打上记忆化标签的状态)。 下面来看一道典型不能使用记忆化搜索的反例: 反例:停在原地的方案数 题目描述 有一个长度为 arrLen 的数组,开始有一个指针在索引 0 处。 从这个角度来说,动态规划和记忆化搜索的共同点在于都是空间换时间的思想。
记忆化搜索:算法上依然是搜索的流程,但是搜索到的一些解用动态规划的那种思想和模式作一些保存。 一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。 记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来, 以后再次遇到这个状态的时候,就不必重新求解了。 下面是一个记忆化搜索的例题: 爬楼梯 有一个n阶的楼梯,每一次可以上1阶或2阶,有多少种方法? #include<stdio.h> long long x[10010],y[10010]; long long Mesch(int i) //Mesch 为 Memory search 记忆化搜索 { int j; if(i==1) return 1; if(i==2) return 2; if(y[i]>0) return y[i]; //记忆化搜索 y[i]=Mesch(i-1)+
验证二叉搜索树 二叉搜索树的中序遍历的结果一定是一个严格递增的序列。 可以初始化一个无穷小的全区变量用来记录中序遍历过程中的前驱结点,那么就可以在中序遍历的过程中,先判断是否和前驱结点构成递增序列,然后修改前驱结点为当前结点,传入下一层的递归中。 K 小的元素 二叉搜索树中第 K 小的元素 中序遍历二叉搜索树,找到第k个数即可。 { tmp += y % 10; y /= 10; } return tmp <= cnt; } }; 3、记忆化搜索 一些题在dfs的时候会有很多重复的工作,如果在这个过程中能将这些结果记录下来,下次dfs的时候先去查找一下先前是否已经搜索过,这会节省很多不必要的时间。
提高效率: 通过保存中间计算结果,记忆化搜索算法能够大幅减少算法的时间复杂度,从指数级别降低到多项式级别。 动态规划: 记忆化搜索在动态规划中经常被使用。 记忆化搜索能够避免重复计算,使得动态规划算法更加高效。 递归算法优化: 记忆化搜索主要用于优化递归算法。 应用于搜索问题: 记忆化搜索不仅用于动态规划,还可以应用于搜索问题,特别是深度优先搜索中的状态记忆。 经典的例子包括斐波那契数列的递归实现、图的最短路径问题中的递归搜索等。 记忆化搜索和动态规划都是一种用于优化递归算法的技术,它们有很多相似之处,但也存在一些关键的区别 记忆化搜索与递归相同与不同 相同之处: 重叠子问题: 记忆化搜索和动态规划都针对具有重叠子问题性质的问题 而在记忆化搜索中,通常直接使用递归调用来表示问题的分解。
记忆化的本质是: 先记录,后返回(记住:一定要记录,否则就是普通的递归); 如果表中有,则直接返回。 ) //{ // if(n==1) return 1; // else if(n==2) return 2; // else return fac(n-1)+fac(n-2); //} //记忆化 int dfs(int t) { int p=1; for(int i=1;i<=t/2;i++) p+=dfs(i); return p; } 改进的代码(记忆化
. ……………… 简单的记忆化搜索,和其他不一样的地方就是这个一次可以走K步,其他没啥!!
验证二叉搜索树 二叉搜索树的中序遍历的结果一定是一个严格递增的序列。 可以初始化一个无穷小的全区变量用来记录中序遍历过程中的前驱结点,那么就可以在中序遍历的过程中,先判断是否和前驱结点构成递增序列,然后修改前驱结点为当前结点,传入下一层的递归中。 K 小的元素 二叉搜索树中第 K 小的元素 中序遍历二叉搜索树,找到第k个数即可。 { tmp += y % 10; y /= 10; } return tmp <= cnt; } }; 5、记忆化搜索 一些题在dfs的时候会有很多重复的工作,如果在这个过程中能将这些结果记录下来,下次dfs的时候先去查找一下先前是否已经搜索过,这会节省很多不必要的时间。
那么你要找出这条路 思路:搜索从每一个点出发的最长距离。不断更新得到最大值 记忆化数组好提高效率!! sizeof(vis)); int ans = 0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ vis[i][j] = dfs(i,j);//记忆化处理
poj 1088 记忆化搜索也也是采用递归深搜的对数据进行搜索,但不同于直接深搜的方式,记忆化搜索是在每次搜索时将得到的结果保存下来,避免了重复计算,这就是所谓的记忆化。 记忆化应该是属于动态规划。 举个例子,比如我们搜索最长最长连续增子序列, 1 2 3 4 5 6 7, 当然这个例子比较特殊,但足以说明情况。 对于这种问题,我们可以先搜索以1开始的,定义一个函数dfs(1), 然后在dfs(1)中将第二个与一个数比较,如果大的话返回1+dfs(2)。。。。 依次递归, 然后我们搜索分别以1 2 …………开头的子序列,当我们dfs(3)时,实际上我们在dfs(2)和dfs(1)的时候早就把它计算过了,如果数据量大的话我们会重复计算多次,但如果我们在计算过程中保存结果
pid=4628 题意:给个字符窜,每步都可以删除一个字符窜,问最少用多少步可以删除一个字符窜 分析:状态压缩+记忆化搜索 先打表,把每一个构成回文的字符窜的状态i都存到一个ss数组中
我们可以试着用搜索的方式进行处理,但是由于数据较大,而且在处理的过程中,有重叠的状态,所以我们需要用到记忆话,对于原先有的状态之后的搜索,我们不去在重复,这样就节省了很多的时间。