首页 > 编程语言 >「代码随想录算法训练营」第四十天 | 动态规划 part13

「代码随想录算法训练营」第四十天 | 动态规划 part13

时间:2024-08-17 14:55:26浏览次数:12  
标签:子串 int part13 训练营 随想录 len ans dp 回文

647. 回文子串

题目链接:https://leetcode.cn/problems/palindromic-substrings/
文章讲解:https://programmercarl.com/0647.回文子串.html
题目难度:中等
视频讲解:https://www.bilibili.com/video/BV17G4y1y7z9/
题目状态:看题解

思路一:动态规划

使用一个二维动规数组dp[i][j]来保存从s[i]s[j](或从s[j]s[i],一样的,本题代码是从j到i)是否属于回文子串。两层遍历该字符串,来记录回文子串的个数。

  • s[i] == s[j]时,要判断一下ij的距离,若i和j的距离为0和1,则表示这是一个回文子串。
  • s[i] == s[j]时,但ij的距离较大,那么就要看其里面的一个是不是回文子串。

代码一:

class Solution {
public:
    int countSubstrings(string s) {
        int len = s.size();
        vector<vector<bool>> dp(len, vector<bool>(len, false));
        int ans = 0;
        for(int i = len - 1; i >= 0; --i) {
            for(int j = i; j < len; ++j) {
                if(s[i] == s[j]) {
                    if(j - i <= 1) {
                        ans++;
                        dp[i][j] = true;
                    } else if(dp[i + 1][j - 1]){
                        ans++;
                        dp[i][j] = true;
                    }
                }
            }
        }
        return ans;
    }
};

思路二:双指针

使用一个辅助函数extend来遍历有多少子串,其中i和j分别是两个起点指针,两个指针分别向前和向后遍历,如果遇到i不等于j的时候,就可以返回了,结果就是以i和j为中间点的子串有多少。而在主函数中,两次调用extend函数分别表示奇子串和偶子串。

代码二:

class Solution {
public:
    int countSubstrings(string s) {
        int ans = 0;
        for(int i = 0; i < s.size(); ++i) {
            ans += extend(s, i, i, s.size());
            ans += extend(s, i, i + 1, s.size());
        }
        return ans;
    }
    int extend(const string &s, int i, int j, int n) {
        int ans = 0;
        while(i >= 0 && j < n && s[i] == s[j]) {
            i--;
            j++;
            ans++;
        }
        return ans;
    }
};

516. 最长回文子序列

题目链接:https://leetcode.cn/problems/longest-palindromic-subsequence/
文章讲解:https://programmercarl.com/0516.最长回文子序列.html
题目难度:中等
视频讲解:https://www.bilibili.com/video/BV1d8411K7W6/
题目状态:看题解

思路:

维护一个动规数组dp[i][j]表示从s[i]s[j]的最长回文子序列的大小。

  • s[i] == s[j]时,表示其是一个回文序列,因此将这两个字符加入进来,即dp[i][j] = dp[i + 1][j - 1] + 2
  • s[i] != s[j]时,我们就需要找在这个范围里的最大子序列的个数了。

代码:

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int len = s.size();
        vector<vector<int>> dp(len, vector<int>(len, 0));
        for(int i = 0; i < len; ++i) dp[i][i] = 1;
        for(int i = len - 1; i >= 0; --i) {
            for(int j = i + 1; j < len; ++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][len - 1];
    }
};

动态规划总结

image

标签:子串,int,part13,训练营,随想录,len,ans,dp,回文
From: https://www.cnblogs.com/frontpen/p/18362167

相关文章

  • 代码随想录算法训练营day09|151.翻转字符串里的单词,卡码网:55.右旋转字符串,28.实现 str
    151.翻转字符串里的单词题目链接:https://leetcode.cn/problems/reverse-words-in-a-string/description/暴力removeExtraSpaces:voidremoveExtraSpaces(string&s){for(inti=s.size()-1;i>0;i--){if(s[i]==''&&s[i]=......
  • 代码随想录day32 || 509 斐波那契数列,70 爬楼梯,746 最小代价爬楼梯
    509斐波那契数列funcfib(nint)int{ //dp五部曲 //1dp数组含义以及下标含义:本题保存的是完整的斐波那契数列,i对应数列的第i个数字 //2递推公式:F(n)=F(n-1)+F(n-2) //3dp数组初始化:由递推公式推到,0,1两位需要手动赋值,否则,oor //4遍历顺序:求......
  • 代码随想录算法训练营第十七天(一)| 654.最大二叉树 617.合并二叉树
    654.最大二叉树题目:给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:创建一个根节点,其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后缀上 构建右子树。......
  • 代码随想录算法训练营第十七天(二)| 700.二叉搜索树中的搜索 98.验证二叉搜索树
    700.二叉搜索树中的搜索题目:给定二叉搜索树(BST)的根节点 root 和一个整数值 val。你需要在BST中找到节点值等于 val 的节点。返回以该节点为根的子树。如果节点不存在,则返回 null 。示例1:输入:root=[4,2,7,1,3],val=2输出:[2,1,3]示例2:输入:roo......
  • 随想录day3:203.移除链表元素|707.设计链表 |206.反转链表
    203.移除链表元素方法一:直接遍历,永远记得处理head,删除链表必须有前驱。/***Definitionforsingly-linkedlist.*publicclassListNode{*intval;*ListNodenext;*ListNode(){}*ListNode(intval){this.val=val;}*ListNode......
  • 【代码随想录】二、链表:2、设计链表
    部分图文参考于:代码随想录-707.设计链表。这道题目设计链表的五个接口:●获取链表第index个节点的数值●在链表的最前面插入一个节点●在链表的最后面插入一个节点●在链表第index个节点前面插入一个节点●删除链表的第index个节点可以说这五个接口,已经覆盖了链表的......
  • 【代码随想录】二、链表:1、移除链表元素
    部分图文参考于:代码随想录-203.移除链表元素。C++编程中记得要手动释放结点内存。链表操作中,可以使用原链表来直接进行删除操作,也可以设置一个虚拟头结点再进行删除操作。1.题目链接203.移除链表元素2.思路以链表1424来举例,移除元素4。如果使用C,C++编程语言的话,......
  • 【代码随想录】二、链表:理论基础
    原文链接:代码随想录-链表理论基础。1.什么是链表?链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。链表的入口节点称为链表的头结点也就是head。2.链表的类型2.1.......
  • 代码随想录 day31|| 56 合并区间,738 单调递增数字,968 监控二叉树
    56合并区间funcmerge(intervals[][]int)[][]int{ //思路先排序,然后按照后一个左区间和前一个右区间进行对比判断是否重叠,重叠扩充右区间 sort.Slice(intervals,func(i,jint)bool{ ifintervals[i][0]==intervals[j][0]{ returnintervals[i][1]<intervals[......
  • 「代码随想录算法训练营」第三十九天 | 动态规划 part12
    115.不同的子序列题目链接:https://leetcode.cn/problems/distinct-subsequences/文章讲解:https://programmercarl.com/0115.不同的子序列.html题目难度:困难视频讲解:https://www.bilibili.com/video/BV1fG4y1m75Q/题目状态:看题解思路:动态规划数组初始化创建一个二维动......