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

记忆化搜索

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

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

动态规划

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

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

二者区别与联系

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

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

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

两者的时间复杂度是相同的,都是 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);
    }

};

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

相关推荐
S01d13r16 分钟前
LeetCode 解题思路 47(最长回文子串、最长公共子序列)
算法·leetcode·职场和发展
摄殓永恒1 小时前
【入门】数字走向II
算法
饮啦冰美式2 小时前
PPO近端策略优化算法
人工智能·深度学习·算法
void_sk2 小时前
C/C++复习--C语言中的函数详细
c语言·c++·算法
evolution_language2 小时前
LintCode第485题-生成给定大小的数组,第220题-冰雹猜想,第235题-分解质因数
数据结构·算法·新手必刷编程50题
钢铁男儿3 小时前
C# 方法(参数数组)
java·算法·c#
KuaCpp3 小时前
5.8线性动态规划2
算法·动态规划
How_doyou_do4 小时前
备战菊厂笔试2-BFS记忆化MLE?用Set去重-Set会TLE?用SortedSet剪枝
算法·深度优先
晴空闲雲5 小时前
线性表-顺序表(Sequential List)
数据结构·算法
Javis2115 小时前
代码随想录算法训练营第九天 |【字符串】151.翻转字符串里的单词、卡码网55.右旋转字符串、28.实现strStr、459.重复的子字符串
数据结构·c++·算法