代码随想录算法训练营第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,否则越界问题,以及不好初始化的问题。

动态规划总结篇

动态规划总结篇

相关推荐
螺旋天光极锐斩空闪壹式!4 分钟前
自制游戏:监狱逃亡
c++·游戏
工业3D_大熊1 小时前
3D可视化引擎HOOPS Luminate场景图详解:形状的创建、销毁与管理
java·c++·3d·docker·c#·制造·数据可视化
暮色_年华1 小时前
Modern Effective C++ Item 11:优先考虑使用deleted函数而非使用未定义的私有声明
c++
流星白龙1 小时前
【C++习题】10.反转字符串中的单词 lll
开发语言·c++
Smile丶凉轩2 小时前
微服务即时通讯系统的实现(服务端)----(1)
c++·git·微服务·github
肥猪猪爸2 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
readmancynn2 小时前
二分基本实现
数据结构·算法
萝卜兽编程2 小时前
优先级队列
c++·算法
盼海2 小时前
排序算法(四)--快速排序
数据结构·算法·排序算法
一直学习永不止步2 小时前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表