【递归,搜索与回溯算法】记忆化搜索(一)

📝前言说明:

  • 本专栏主要记录本人递归,搜索与回溯算法的学习以及LeetCode刷题记录,按专题划分
  • 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
  • 文章中的理解仅为个人理解。如有错误,感谢纠错

🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础python入门基础C++学习笔记Linux
🎀CSDN主页 愚润泽

你可以点击下方链接,进行该专题内不同子专题的学习

点击链接开始学习
导论递归 (一)递归 (二)
二叉树的深搜穷举 vs 暴搜 vs 深搜 vs 回溯 vs 剪枝
综合练习(一)综合练习(二)
综合练习(三)综合练习(四)
FloodFill(一)FloodFill(二)
记忆化搜索(一)记忆化搜索(二)

题单汇总链接:点击 → 题单汇总


专题开篇导论(以509. 斐波那契数为例)

题目链接:https://leetcode.cn/problems/fibonacci-number/description/
在这里插入图片描述
记忆化搜索是带备忘录的递归(用于在递归时出现重复结果的情况)
普通递归展开图:
在这里插入图片描述

1. 记忆化搜索

我们可以发现:d(2), d(3)被重复计算了(出现重复问题),因此我们可以引入一个备忘录

  • 在递归返回之前把结果加入备忘录
  • 在递归展开之前,先找找备忘录里面是否有当前要展开的“数”的结果
  • 注意:备忘录的初始化:要让备忘录的初始化值为不可能出现的结果,即:不会影响后续的搜索

代码实现:

class Solution {
public:
    vector<int> hash = vector<int>(31, -1);
    int dfs(int n)
    {
        // 先找备忘录
        if(hash[n] != -1)
            return hash[n];
        // 递归展开
        if(n == 1 || n == 0)
        {
            hash[n] = n; // 把结果加入备忘录
            return hash[n];
        }
        hash[n] = dfs(n - 1) + dfs(n - 2); // 结果加入备忘录
        return hash[n];
    }
    int fib(int n) 
    {
        return dfs(n);
    }
};

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)

2. 记忆化搜索对比动态规划

记忆化搜索和动态规划都是对暴力解法的优化 → 把计算过的值“存起来”
在这里插入图片描述

  • 带备忘录的递归 vs 带备忘录的动态规划(普通动态规划) vs 记忆化搜索:都是一回事
  • 暴搜 + 记忆化搜索 →(可以转换成) 动态规划
    • 但是不建议所有的题目都这样做,要具体题目具体分析
    • 暴搜可以给我们动态规划的状态表示提供一个方向

62. 不同路径

题目链接:https://leetcode.cn/problems/unique-paths/description/
在这里插入图片描述

个人解

思路:

  • 简单练习题,不说了

用时:6:00
屎山代码:

class Solution {
public:
    int dfs(int x, int y, vector<vector<int>>& mem)
    {
        // 先找mem
        if(mem[x][y] != 0)
            return mem[x][y];

        // 递推自顶向下,回归是自底向上的,所以递归的结束条件应该观察底
        if(x == 0 || y == 0) // 最左边那一路和左右边那一路都只有一种走法
        {
            mem[x][y] = 1;
            return mem[x][y];
        }
        mem[x][y] = dfs(x - 1, y, mem) + dfs(x, y - 1, mem);
        return mem[x][y]; // 不会越界因为上面约束了   
    }
    int uniquePaths(int m, int n) 
    {
        vector<vector<int>> mem(m + 1, vector<int>(n + 1));
        return dfs(m - 1, n - 1, mem);
    }
};

时间复杂度: O ( m ∗ n ) O(m*n) O(mn)
空间复杂度: O ( m ∗ n ) O(m*n) O(mn)


🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愚润泽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值