记忆化搜索和动态规划 --最长回文子串为例

记忆化搜索

记忆化搜索是一种优化递归算法的方法,通过将已经计算过的子问题的结果存储起来(通常使用哈希表或数组),避免重复计算相同的子问题。

本质上是通过缓存中间结果来减少计算的重复性。

动态规划

动态规划是通过将问题分解成子问题来解决的,它通常通过表格化的方式(自底向上)来存储子问题的解,以便在需要时能够快速访问。

动态规划的核心思想是通过自底向上的方式来解决问题,通常使用一个数组或表格来存储每个子问题的解,从而避免了递归的重复计算。

二者区别与联系

记忆化搜索和动态规划的区别,主要在于计算的顺序。

记忆化搜索通常是自顶向下的递归方式,在递归中检查子问题是否已经计算过,并存储结果。

动态规划通常是自底向上的方式,逐步计算所有子问题,并存储所有的中间结果,最终得到问题的解。

两者的时间复杂度是相同的,都是 O(n),因为两者都避免了重复计算子问题。

例题

最长回文子串 -力扣

记忆化搜索解答:

class Solution {
public:
    int dp[1000][1000];
    std::string ss;
    bool judge(int l, int r) {
        if (dp[l][r] != -1) {
            return dp[l][r];
        }

        if (ss[l] == ss[r]) {
            if (r - l > 1) {
                if (dp[l + 1][r - 1] == -1) {
                    dp[l][r] = judge(l + 1, r - 1);
                } else {
                    dp[l][r] = dp[l + 1][r - 1];
                }
            } else {
                dp[l][r] = 1;
            }
        } else {
            dp[l][r] = 0;
        }
        return dp[l][r];
    }

    std::string longestPalindrome(std::string s) {
        memset(dp,-1,sizeof(dp));
        int len = s.length();
        ss = s;
        int res = 0;
        int l = 0;

        for (int i = 0; i < len; i++) {
            for (int j = i; j < len; j++) {
                dp[i][j] = judge(i, j);
                if (dp[i][j] == 1 && j - i > res) {
                    res = j - i;
                    l = i;
                }
            }
        }

        return s.substr(l, res + 1);
    }
};

动态规划解答

class Solution {
public:
    std::string longestPalindrome(std::string s) {
        int len = s.length();
        bool dp[1000][1000];

        memset(dp,false,sizeof(dp));

        for(int i = len - 1; i >= 0; i--){
            for(int j = i; j < len; j++){
                if(s[i] != s[j]){
                    dp[i][j] = false;
                }
                else{
                    if(i == j){
                        dp[i][j] = true;
                    }
                    else{
                        if(j - i == 1){
                            dp[i][j] = true;
                        }
                        else{
                            dp[i][j] = dp[i+1][j-1];
                        }
                    }
                }
            }
        }
        int res = 0;
        int l = 0;

        for(int i = 0; i < len; i++){
            for(int j = i; j < len; j++){
                if(dp[i][j] == true){
                    if(res < j - i){
                        res = j - i;
                        l = i;
                    }
                }
            }
        }

        return s.substr(l,res + 1);
    }

};

由于函数调用的原因,使用递归的记忆化搜索算法的时间会稍微久一点

相关推荐
记得早睡~10 分钟前
leetcode654-最大二叉树
javascript·数据结构·算法·leetcode
旧厂街小江15 分钟前
LeetCode 第63题:不同路径 II
算法·程序员·架构
写代码的橘子n29 分钟前
unordered_set 的常用函数
数据结构·算法·哈希算法
EnigmaCoder40 分钟前
蓝桥杯刷题周计划(第二周)
学习·算法·蓝桥杯
黑金IT44 分钟前
深入理解人脸特征向量及图片转换方法与开发架构
算法·架构
HP-Patience1 小时前
决策树 vs 神经网络:何时使用?
神经网络·算法·决策树
AI很强1 小时前
matlab常见的配图代码实现1
开发语言·算法·matlab
飞川0011 小时前
🚀 力扣热题 78:子集(详细解析)
算法
*.✧屠苏隐遥(ノ◕ヮ◕)ノ*.✧1 小时前
C语言_数据结构总结6:链式栈
c语言·开发语言·数据结构·算法·链表·visualstudio·visual studio
田梓燊2 小时前
leetcode 95.不同的二叉搜索树 Ⅱ
数据结构·算法·leetcode