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

记忆化搜索

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

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

动态规划

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

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

二者区别与联系

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

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

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

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

};

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

相关推荐
爱coding的橙子39 分钟前
每日算法刷题Day19 5.31:leetcode二分答案3道题,用时1h
算法·leetcode·职场和发展
地平线开发者2 小时前
征程 6EM 常见 QConfig 配置解读与示例
算法·自动驾驶
GEEK零零七2 小时前
Leetcode 1908. Nim 游戏 II
算法·leetcode·博弈论
sbc-study2 小时前
混沌映射(Chaotic Map)
开发语言·人工智能·python·算法
Magnum Lehar3 小时前
vulkan游戏引擎game_types.h和生成build.bat实现
java·算法·游戏引擎
Christophe Chen3 小时前
strcat及其模拟实现
c语言·算法
独家回忆3644 小时前
每日算法-250531
算法
@我漫长的孤独流浪4 小时前
数据结构测试模拟题(2)
数据结构·c++·算法
秋难降4 小时前
贪心算法:看似精明的 “短视选手”,用好了也能逆袭!💥
java·算法