记忆化搜索 Memorization Search

  • 什么是记忆化搜索
  • 记忆化搜索函数的三个特点
  • 记忆化搜索 vs 动态规划
  • 三种适用于DP的场景
  • 三种不适用于DP的场景
  • Examples:
    • Leetcode 140: 单词拆分 II
    • Leetcode 44: 通配符匹配

什么是记忆化搜索

  • 在递归函数中, 在函数返回前,记录函数的返回结果。在下一次以同样参数访问函数时直接返回记录下的结果
  • 也就是对递归树进行剪枝,遇到已经计算过的节点就不再继续往下计算,直接返回储存在hash table中的值

记忆化搜索函数的三个特点

  • 函数有返回值
  • 函数返回结果和输入参数有关,和其他全局状态无关
  • 参数列表中传入哈希表或者其他用于记录计算结果的数据结构

记忆化搜索 vs 动态规划

  • 记忆化搜索是动态规划的一种实现方式, 也就是top-down approach
  • 动态规划的另一种实现方式是多重循环 (找出动态转移方程,循环遍历), 也就是bottom-up approach

三种适用于DP的场景

三种不适用于DP的场景

Examples:

Leetcode 140: 单词拆分 II

/*
利用dfs搜索 + 回溯
对于字符串 ss,如果某个前缀是单词列表中的单词,则拆分出该单词,然后对 s 的剩余部分继续拆分。如果可以将整个字符串 s 拆分成单词列表中的单词,则得到一个句子
Example:
catsanddog
c 不在字典里
ca 不在字典里
cat在字典里,所以将剩余部分 sanddog 送入递归, 进入下一层
以此类推
回溯时将每一层的字符串加入前一层返回的字符串优化: 记忆化搜索
以上方法在个别测试用例时会超时,所以需要记忆化搜索剪枝
第一次查找后,用一个map记录每个index的答案
下次再遇到就直接用
*/class Solution {public List<String> wordBreak(String s, List<String> wordDict) {//用一个map实现记忆化搜索: <index, 这个index之后的所有答案>Map<Integer, List<String>> memo = new HashMap<>(); return dfs(s, wordDict, 0, memo);}public List<String> dfs(String s, List<String> wordDict, int startIndex, Map<Integer, List<String>> memo) {//查看目前的startIndex是否已经被查找过,如果是,则直接返回答案if (memo.get(startIndex) != null) {return memo.get(startIndex);}//如果startIndex等于length,则说明已经触底,返回空if (startIndex == s.length()) {List<String> list = new ArrayList<>();list.add("");return list;}List<String> ans = new ArrayList<>();for (int i = startIndex; i <= s.length(); i++) {//如果startIndex到 i - 1 组成的字符串在字典里 (substring方法不包括最后的i,所以for loop是  i <= s.length())if (wordDict.contains(s.substring(startIndex, i))) {//i为startIndex,进入下一次递归List<String> tempList = dfs(s, wordDict, i, memo);//处理返回的答案,将startIndex到i组成的字符串加入到 返回的list中的每个字符串for (String tempString: tempList) {//如果字符串为空,则后面不能有空格,特殊处理if (tempString == "") {ans.add(s.substring(startIndex, i));continue;}ans.add(s.substring(startIndex, i) + " " + tempString);}}//记录startIndex的所有答案memo.put(startIndex, ans);}return ans;}
}

Leetcode 44: 通配符匹配

/*
本题有两种解法:
第一种:记忆化递归
分别用ss和pp遍历字符串s和p
case 1:如果 ss==pp 或者 pp= "?" 则ss++, pp++, 进入下一层递归
case 2:如果 pp == "*"for (int i = s_start; i <= s.length(); i++) {将 i 和 pp + 1 送入递归函数, 进行对比}使用两个boolean数组:记录 visited[i][j] 和 results[i][j]第二种:动态规范
*/class Solution {public boolean isMatch(String s, String p) {if (s ==null || p == null) {return false;}boolean [][] visited = new boolean[s.length()][p.length()];boolean [][] results = new boolean[s.length()][p.length()];return helper(s, 0, p, 0, visited, results);}public boolean helper(String s, int s_start, String p, int p_start,boolean [][] visited, boolean [][] results) {//如果p_start等于p.length,则说明p字符串已经处理完毕,s需要也处理完毕,否则就是false    //注意这里是p.length 不是 p.length - 1                 if (p_start == p.length()) {return s_start == s.length();}//如果s字符串处理完毕,则p剩下的字符需要全部是 *if (s_start == s.length()) {return ifAllStar(p, p_start);}//判断目前的index是否处理过if (visited[s_start][p_start]) {return results[s_start][p_start];}char pp = p.charAt(p_start);char ss = s.charAt(s_start);boolean match = false;if (pp != '*') { //如果 ss==pp 或者 pp= "?" 则ss++, pp++, 进入下一层递归match = ifSameChar(ss, pp) && helper(s, s_start + 1, p, p_start + 1, visited, results);}else {//这行代码和下面注释掉的fou loop是一个意思, 本质是 将 i不断递增 然后 和 pp + 1 送入递归函数, 进行对比//注释掉的代码有点慢match = helper(s, s_start, p, p_start + 1, visited, results) || helper(s, s_start + 1, p, p_start, visited, results);}/*else {for (int i = s_start; i <= s.length(); i++) {match = helper(s, i, p, p_start + 1, visited, results) || match;}}*/results[s_start][p_start] = match;visited[s_start][p_start] = true;return match;}private boolean ifAllStar(String p, int p_start) {for(int i = p_start; i < p.length(); i++) {if (p.charAt(i) != '*') {return false;}}return true;}private boolean ifSameChar(char s, char p) {return (s == p || p == '?');}
}

记忆化搜索 Memorization Search相关推荐

  1. 记忆化搜索(Memory Search)

    Question 输入n,符合要求的序列为:第一个数为n,第二个数不大于n,从第三个数起小于前两个数的差的绝对值,后面以此类推.求有多少种序列?答案取模10000(数据:n最大为1000) Sampl ...

  2. 洛谷P1057 传球游戏(记忆化搜索)

    点我进入题目 题目大意:n个小孩围一圈传球,每个人可以给左边的人或右边的人传球,1号小孩开始,一共传m次,请问有多少种可能的路径使球回到1号小孩. 输入输出:输入n,m,输出路径的数量. 数据范围:4 ...

  3. UVA 10158 (记忆化搜索)

    题目大意: 已知有n个人,他们之间有敌对还有友好关系,已知: 自己和自己为好友. a和b为好友,那么b和a也为好友 自己的敌人是敌人. 自己和自己不能为敌人. a和b为敌人,那么b和a也为敌人 敌人的 ...

  4. 01迷宫(记忆化搜索)

    01迷宫 题目描述: 有一个由01组成的n*n格迷宫,若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上.那么对于给定的迷宫,询问从 ...

  5. 对记忆化搜索(ms)和动态规划(dp)的深入理解

    六月中旬了,马上就要期末考试了,期末考试结束以后就要迎来紧张刺激的留校集训,到那时博客会更新的比较频繁,而现在在准备期末考试,所以可能更新的博客稍微少一些. 话不多说,今天来更一篇刚刚吃饭的时候关于记 ...

  6. 图论 ---- F. Graph Traveler 记忆化搜索 + 思维预处理(数论同余恒等式)

    题目链接 题目大意: q∈[1,1e5],n∈[1,1000],mi∈[1,10]q\in[1,1e5],n\in[1,1000],m_i\in[1,10]q∈[1,1e5],n∈[1,1000],m ...

  7. 思维dp ---- Codeforces Round #711 (Div. 2) - C. Planar Reflections[dp/记忆化搜索]

    题目链接 题目大意: 就是给你n个平面和一个寿命为k的衰变粒子.开始粒子从左向右飞行,粒子每经过一个平面就会产生一个副本粒子,这个副本粒子比原粒子的寿命少1,即为k-1,并且飞行方向是原粒子的反方向. ...

  8. Discovering Gold LightOJ - 1030[概率dp或者记忆化搜索]

    题目大意:有一个[1,n][1,n][1,n]的数轴,数轴上的每个对应位置上都有金矿,你初始位置是1,然后你每次都会投色子决定你下一步跳到哪里,如果你跳出了nnn,那么你就要重新投.问你跳到nnn的时 ...

  9. BZOJ 1589 Trick or Treat on the Farm (tarjan缩点,记忆化搜索)[Usaco 2008 Dec Gold]【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Weblink https://hydro.ac/d/bzoj/p/1589 Problem 每年万圣 ...

最新文章

  1. 如何在系统崩溃时从C++中获取函数调用栈信息?
  2. 软件测试_APP测试_兼容性测试
  3. unity 半透明混合问题_Unity 实时 半透明 阴影 shader
  4. windows驱动开发学习
  5. 数据卡片_手把手教你构建企业实时数据大屏
  6. 一图读懂|H3C SecPath ACG1050-X1应用控制网关
  7. 不占内存的浏览器_4款黑科技办公网站,高效实用,不占内存,高手的必备神器...
  8. Hadoop——MapReduce(3)
  9. 微信公众号-回复消息触发时间绑定EventKEY
  10. Word论文用的各级标题大小
  11. win10怎么在开机时自动连接拨号上网
  12. 魔兽世界私服架设 服务器架设简易教程
  13. HDU 1241 Oil Deposits(石油储藏)
  14. 视频转换成gif动图如何操作?教你三步完成视频转gif
  15. anaconda python降级有影响吗_anaconda更新所有降级包
  16. 中科红旗倒下,谁来挑战windows
  17. html插缝小游戏,HTML5游戏 - 见缝插针
  18. 沟通修炼 I型沟通->U型沟通
  19. Humble Numbers (谦卑数 || 丑数)
  20. 8188gu驱动和su realtek_Realtek全系列官方网卡驱动

热门文章

  1. 多线程之哲学家就餐问题(java代码含注释)
  2. Php斐波那契数列尾递归优化,递归优化的这三种方式你知道吗?
  3. 华为mate 10升级鸿蒙,华为10款机型升级EMUI11,为鸿蒙做准备,荣耀脱离这是要大变革?...
  4. win7web服务器设置默认网页,教你win7配置web服务器的方法
  5. MATLAB中多行注释以及取消的快捷键
  6. 公钥、私钥、证书、加密、解密、加签、验签
  7. 常见近红外/红外光谱数据预处理方法及MATLAB实现
  8. 2.口袋西游人物属性(02)
  9. PHP服务计时器,JS计时器
  10. 【转】记一次 ClickHouse 数据迁移