代码随想录算法训练营第40天 | 第九章动态规划 part13

文章目录

  • [第九章 动态规划 part13](#第九章 动态规划 part13)

第九章 动态规划 part13

今天我们就要结束动态规划章节了,大家激不激动!!!

详细布置

647. 回文子串

动态规划解决的经典题目,如果没接触过的话,别硬想,直接看题解。
647. 回文子串

看似很难,实际上确实挺难。

我们将使用输入字符串 s = "aba" 来填充 dp 数组,并展示其每个元素的值。

好的,下面我们来展示字符串 s = "abab" 的三乘三 dp 数组。

对于字符串 s = "abab",我们会通过填充 dp 数组来表示不同子串是否为回文。

填充 dp 数组过程

我们根据判断子串是否为回文,逐步填充 dp 数组:

  1. i=3, j=3 :子串 "b",单字符总是回文,dp[3][3] = 1
  2. i=2, j=2 :子串 "a",单字符总是回文,dp[2][2] = 1
  3. i=2, j=3 :子串 "ab"s[2] != s[3],不是回文,dp[2][3] = 0
  4. i=1, j=1 :子串 "b",单字符总是回文,dp[1][1] = 1
  5. i=1, j=2 :子串 "ba"s[1] != s[2],不是回文,dp[1][2] = 0
  6. i=1, j=3 :子串 "bab"s[1] == s[3] 且子串 dp[2][2] = 1(即 "a" 是回文),因此 dp[1][3] = 1
  7. i=0, j=0 :子串 "a",单字符总是回文,dp[0][0] = 1
  8. i=0, j=1 :子串 "ab"s[0] != s[1],不是回文,dp[0][1] = 0
  9. i=0, j=2 :子串 "aba"s[0] == s[2] 且子串 dp[1][1] = 1(即 "b" 是回文),因此 dp[0][2] = 1
  10. i=0, j=3 :子串 "abab"s[0] != s[3],不是回文,dp[0][3] = 0

最终 dp 数组

a b a b
a 1 0 1 0
b 1 0 1
a 1 0
b 1

总结

最终 dp 数组表示了字符串 s 中各个子串的回文状态,1 表示回文,0 表示非回文。

cpp 复制代码
class Solution {
public:
    int countSubstrings(string s) {
        int count = 0;
 vector<vector<int>> dp(s.size() , vector<int>(s.size() , 0));
        for (int i = s.size()-1; i >=0; i--) {
            for (int j = i; j < s.size(); j++) {
                if (s[i ] == s[j ]) {
                    if ( j-i <= 1) {
                        count++;  
                    dp[i][j] = 1;
                   } 
                else if (dp[i + 1][j - 1]) { // 情况三
                       count++;  
                        dp[i][j] = 1;
                    }      
                } 
            }    
         }
    return count;
    }
};

难度还是有些的,多按照上面的思路整理下,也还好,左下角代表的意思是判断中间部分是否回文。

双指针
cpp 复制代码
class Solution {
public:
int extend(const string& s, int i, int j, int n){
   int num=0;
    while(i>=0&&j<n&&s[i]==s[j])
    {
        i--;
        j++;
        num++;
    }
    return num;
}
int countSubstrings(string s) {
        int count = 0;
        for(int i=0;i<s.size();i++)
        {
            count+=extend(s,i,i,s.size());
            count+=extend(s,i,i+1,s.size());
        }
        return count;
    }
};

双指针法确实好简单呢。只要一个个遍历中心点,然后朝两处扩散。注意,中心点可能是基数,也可能是偶数。所以要分两种情况,最开始我还担心,会不会数组越界。for循环怎么写。要在for循环后面补一行吗?但是子函数完全不用担心。因为虽然i+1==s.size(),能进入子函数,但是不能进入while循环,直接返回0。不用担心。

516. 最长回文子序列

  1. 回文子串,求的是回文子串,而本题要求的是回文子序列,大家要搞清楚两者之间的区别。

516. 最长回文子序列

最开始还以为回文子序列,直接双指针法秒了或者动态规划法秒了。结果发现回文子序列。确实难度增加了。得好好思考了。

cpp 复制代码
class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int count=0;
        int n=s.size();
        vector<vector<int>> dp(n , vector<int>(n , 0));
        for (int i = 0; i < n; ++i) {
            dp[i][i] = 1;
        }
        for (int i = n-2; i >=0; i--) {
            for (int j = i+1; j < n; j++) {
                if (s[i ] == s[j ]) {
                    dp[i][j]=dp[i + 1][j - 1]+2;
                    }
                    else{
                        dp[i][j]=max(dp[i + 1][j ],dp[i ][j-1] );
                }
            } 
        }
        return dp[0][n-1]; 
     }
};

整体思路和原先完全类似,把这幅图的思路看懂即可。初始化要把对角线初始化为1,否则越界问题,以及不好初始化的问题。

动态规划总结篇

动态规划总结篇

相关推荐
努力写代码的熊大3 分钟前
八大排序算法
java·算法·排序算法
xiaobaibai15342 分钟前
智慧交通中目标检测 mAP↑28%:陌讯多模态融合算法实战解析
人工智能·算法·目标检测·计算机视觉·目标跟踪·视觉检测
战争热诚1 小时前
基于transformer的目标检测——匈牙利匹配算法
算法·目标检测·transformer
计算机科研圈1 小时前
ICCV 2025 | EPD-Solver:西湖大学发布并行加速扩散采样算法
人工智能·算法·语言模型·自然语言处理·数据挖掘·iccv
清朝牢弟1 小时前
Ubuntu系统VScode实现opencv(c++)图像放缩与插值
c++·vscode·opencv·ubuntu·计算机视觉
呆瑜nuage1 小时前
list的使用和模拟
c++·list
Yzxs0091 小时前
【8月优质EI会议合集|高录用|EI检索稳定】计算机、光学、通信技术、电子、建模、数学、通信工程...
大数据·人工智能·算法·计算机视觉·信息与通信
tomato091 小时前
Codeforces Round 1040 (Div. 2)(补题)
c++
好好先森&2 小时前
C语言:模块化编程
c语言·c++·windows
爱学习的小邓同学2 小时前
c++ --- priority_queue的使用以及简单实现
c++