动态规划算法专题(六):回文串问题

news2024/10/10 5:42:28

目录

1、回文子串("引子题")

1.1 算法原理 

1.2 算法代码

2、最长回文子串

2.1 算法原理

2.2 算法代码

3、分割回文串 IV(hard)

3.1 算法原理

3.2 算法代码

4、分割字符串 II(hard)

4.1 算法原理 

4.2 算法代码

5、最长回文子序列

5.1 算法原理 

5.2 算法代码

6、让字符串成为回文串的最少插入次数(hard)

6.1 算法原理

6.2 算法代码


1、回文子串("引子题")

. - 力扣(LeetCode)

1.1 算法原理 

  • 状态表示:

dp[i][j]:[i, j]区间内的子串,是否回文(i <= j)

  • 状态转移方程:

s[i] == s[j]:

1. i == j --> true 
2. i+1==j --> s(i) == s(j) ? true : false
3. s(i) == s(j) --> dp[i+1][j-1]

  • 初始化:

无需初始化(状态转移方程的前两种情况已处理特殊的边界情况)

  • 建表顺序:

从下往上(根据状态转移方程)

  • 返回值:

dp表中有几个true

1.2 算法代码

class Solution {
    public int countSubstrings(String ss) {
        char[] s = ss.toCharArray();
        int n = s.length;
        boolean[][] dp = new boolean[n][n];
        int ret = 0;
        // 填表 --> 从下往上
        for(int i = n - 1; i >= 0; i--) {
            // j >= i
            for(int j = i; j < n; j++) {
                if(s[i] == s[j]) {
                    if(i == j) dp[i][j] = true;
                    else if(i + 1 == j) dp[i][j] = true;
                    else dp[i][j] = dp[i + 1][j - 1];
                }
                if(dp[i][j]) ret++;
            }
        }
        return ret;
    }
}

2、最长回文子串

. - 力扣(LeetCode)

2.1 算法原理

本题算法原理与题一完全一致,最终返回最长的回文子串即可。

  • 状态表示:

dp[i][j]:[i, j]区间内的子串,是否回文(i <= j)

  • 状态转移方程:

s[i] == s[j]:

1. i == j --> true 
2. i+1==j --> s(i) == s(j) ? true : false
3. s(i) == s(j) --> dp[i+1][j-1]

  • 初始化:

无需初始化(状态转移方程的前两种情况已处理特殊的边界情况)

  • 建表顺序:

从下往上(根据状态转移方程)

  • 返回值:

最长回文子串

2.2 算法代码

class Solution {
    public String longestPalindrome(String ss) {
        char[] s = ss.toCharArray();
        int n = s.length;
        boolean[][] dp = new boolean[n][n];
        String ret = "";
        int begin = 0;
        int end = 0;
        // 建表 --> 从下往上
        for(int i = n - 1; i >= 0; i--) {
            for(int j = i; j < n; j++) {// i <= j
                if(s[i] == s[j]) {
                    if(i == j) dp[i][j] = true;
                    else if(i + 1 == j) dp[i][j] = true;
                    else dp[i][j] = dp[i + 1][j - 1];
                }
                if(dp[i][j]) {
                    // 记录最长回文子串的起始和末尾位置
                    if(j - i + 1 > end - begin + 1) {
                        begin = i;
                        end = j;
                    }
                } 
            }
        }
        return ss.substring(begin, end + 1);
    }
}

3、分割回文串 IV(hard)

. - 力扣(LeetCode)

3.1 算法原理

本题算法原理依旧是在题一判断好哪些子串是回文的基础上,分割字符串,判断是否存在三个回文串即可。

  • 状态表示:

dp[i][j]:[i, j]区间内的子串,是否回文(i <= j)

  • 状态转移方程:

s[i] == s[j]:

1. i == j --> true 
2. i+1==j --> s(i) == s(j) ? true : false
3. s(i) == s(j) --> dp[i+1][j-1]

  • 初始化:

无需初始化(状态转移方程的前两种情况已处理特殊的边界情况)

  • 建表顺序:

从下往上(根据状态转移方程)

  • 返回值:

是否存在三个回文串。

3.2 算法代码

class Solution {
    public boolean checkPartitioning(String ss) {
        char[] s = ss.toCharArray();
        int n = s.length;
        boolean[][] dp = new boolean[n][n];
        for(int i = n - 1; i >= 0; i--) {
            for(int j = i; j < n; j++) {
                if(s[i] == s[j]) {
                    if(i == j) dp[i][j] = true;
                    else if(i + 1 == j) dp[i][j] = true;
                    else dp[i][j] = dp[i + 1][j - 1];
                }
            }
        }
        // 从 i,j 位置 分割字符串
        for(int i = 1; i < n; i++) {
            for(int j = i; j < n - 1; j++) {
                if(dp[0][i - 1] && dp[i][j] && dp[j + 1][n - 1]) return true;
            }
        }
        return false;
    }
}

4、分割字符串 II(hard)

. - 力扣(LeetCode)

4.1 算法原理 

本题仍然在题一中 通过二维dp保存所有子串的是否回文的信息 的基础上解题。

  • 状态表示:

dp[i]:以[0, i]区间内的子串,最少的分割次数

  • 状态转移方程:

1. 0~i 回文 --> 0
2. 0~i 不回文 --> 0 < j < = i --> 若子串[ j, i ]回文 --> min(dp[ j - 1 ] + 1)

  • 初始化:

dp表中所有元素初始化为Integer.MAX_VALUE

  • 建表顺序:

从左往右

  • 返回值:

dp[n-1]

4.2 算法代码

class Solution {
    public int minCut(String ss) {
        char[] s = ss.toCharArray();
        int n = s.length;
        boolean[][] isPal = new boolean[n][n];
        for (int i = n - 1; i >= 0; i--) {
            for (int j = i; j < n; j++) {
                if (s[i] == s[j]) {
                    if (i == j)
                        isPal[i][j] = true;
                    else if (i + 1 == j)
                        isPal[i][j] = true;
                    else
                        isPal[i][j] = isPal[i + 1][j - 1];
                }
            }
        }
        int[] dp = new int[n];
        // 初始化
        Arrays.fill(dp, Integer.MAX_VALUE);
        for (int i = 0; i < n; i++) {
            if (isPal[0][i])
                dp[i] = 0;
            else {
                // j --> (0, i]
                for (int j = 1; j <= i; j++) {
                    if (isPal[j][i])
                        dp[i] = Math.min(dp[i], dp[j - 1] + 1);
                }
            }
        }
        return dp[n - 1];
    }
}

5、最长回文子序列

. - 力扣(LeetCode)

5.1 算法原理 

  • 状态表示:

dp[i][j]:s字符串[i , j]区间内的所有子序列中,最长回文子序列的长度

  • 状态转移方程:

1. s[i] == s[j]:

i==j --> 1
i+1==j --> 2
dp[i+1][j-1]+2

2. s[i] != s[j]:

max(dp[i][j-1], dp[i+1][j])

  • 初始化:

无需初始化

  • 建表顺序:

从下往上填写每一行,每一行从左往右填写每一列

  • 返回值:

dp[0][n-1]

5.2 算法代码

class Solution {
    public int longestPalindromeSubseq(String ss) {
        char[] s = ss.toCharArray();
        int n = s.length;
        int[][] dp = new int[n][n];
        // 从下往上填每一行
        // 每一行从左往右填每一列
        for(int i = n - 1; i >= 0; i--) {
            for(int j = i; j < n; j++) {
                if(s[i] == s[j]) {
                    if(i == j) dp[i][j] = 1;
                    else if(i + 1 == j) dp[i][j] = 2;
                    else dp[i][j] = dp[i + 1][j - 1] + 2;
                }else {
                    dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[0][n - 1];
    }
}

6、让字符串成为回文串的最少插入次数(hard)

. - 力扣(LeetCode)

6.1 算法原理

  • 状态表示:

dp[i][j]:字符串[i, j]区间内的子串,使它成为回文串的最小插入次数

  • 状态转移方程:

s[i] == s[j]:

1. i == j --> 0

2. i + 1 == j --> 0

3. dp[i + 1][j - 1]

s[i] != s[j]:

min(dp[i + 1][j], dp[i][j - 1]) + 1;

  • 初始化:

无需初始化

  • 建表顺序:

从上到下每一行
从左往右每一列

  • 返回值:

dp[0][n-1]

6.2 算法代码

class Solution {
    public int minInsertions(String ss) {
        char[] s = ss.toCharArray();
        int n = s.length;
        int[][] dp = new int[n][n];
        // 无需初始化
        // 建表 --> 从上往下每一行,从左往右每一列
        for(int i = n - 1; i >= 0; i--) {
            for(int j = i; j < n; j++) {
                if(s[i] == s[j]) {
                    if(i == j) dp[i][j] = 0;
                    else if(i + 1 == j) dp[i][j] = 0;
                    else dp[i][j] = dp[i + 1][j - 1];
                }else dp[i][j] = Math.min(dp[i + 1][j], dp[i][j - 1]) + 1;
            }
        }
        return dp[0][n - 1];
    }
}

END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2201200.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

甲虫身体图像分割系统源码&数据集分享

甲虫身体图像分割系统源码&#xff06;数据集分享 [yolov8-seg-EfficientRepBiPAN&#xff06;yolov8-seg-C2f-FocusedLinearAttention等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challen…

C语言之扫雷小游戏(完整代码版)

说起扫雷游戏&#xff0c;这应该是很多人童年的回忆吧&#xff0c;中小学电脑课最常玩的必有扫雷游戏&#xff0c;那么大家知道它是如何开发出来的吗&#xff0c;扫雷游戏背后的原理是什么呢&#xff1f;今天就让我们一探究竟&#xff01; 扫雷游戏介绍 如下图&#xff0c;简…

从0开始linux(12)——命令行参数与环境变量

欢迎来到博主的专栏&#xff1a;从0开始linux 博主ID&#xff1a;代码小豪 文章目录 命令行参数环境变量 我们先打断一下关于进程的话题&#xff0c;博主先来介绍两个东西&#xff0c;分别是命令行参数与环境变量。那么有人看到这就会问了&#xff0c;难道说命令行参数和环境变…

Spring系列 循环依赖

文章目录 注入方式循环依赖的场景单例创建流程getSingletoncreateBeandoCreateBeancreateBeanInstance 循环依赖分析为什么都使用构造函数无法解决&#xff1f;为什么使用Autowired可以解决&#xff1f;为什么要添加到 earlySingletonObjects 缓存中&#xff1f;allowCircularR…

基于Kafka2.1解读Producer原理

文章目录 前言一、Kafka Producer是什么&#xff1f;二、主要组件1.Kafka Producer1.1 partitioner1.2 keySerializer1.3 valueSerializer1.4 accumulator1.5 sender 2.Sender2.1 acks2.2 clientinFlightBatches 3. Selector3.1 nioSelector3.2 channels 4. 全局总览 总结 前言…

【hot100-java】N 皇后

回溯篇 视频题解 真的裂开了&#xff0c;多看视频题解。 class Solution {public List<List<String>> solveNQueens(int n) {List<List<String>>retnew ArrayList<>();int []colnew int[n];boolean[] onPathnew boolean[n];boolean[] diag1ne…

(Linux和数据库)1.Linux操作系统和常用命令

了解Linux操作系统介绍 除了办公和玩游戏之外不用Linux&#xff0c;其他地方都要使用Linux&#xff08;it相关&#xff09; iOS的本质是unix&#xff08;unix是付费版本的操作系统&#xff09; unix和Linux之间很相似 Linux文件系统和目录 bin目录--放工具使用的 操作Linux远程…

双光吊舱图像采集详解!

一、图像采集 可见光图像采集&#xff1a; 使用高性能的可见光相机&#xff0c;通过镜头捕捉自然光或人工光源照射下的目标图像。 相机内部通常配备有先进的图像传感器&#xff0c;如CMOS或CCD&#xff0c;用于将光信号转换为电信号。 红外图像采集&#xff1a; 利用红外热…

【hot100-java】二叉树的最近公共祖先

二叉树篇 我觉得是比两个节点的深度&#xff0c;取min&#xff08;一种情况&#xff09; DFS解题。 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val x; }* }*/ clas…

Unity/VS 消除不想要的黄色警告

方法一&#xff1a;单个消除 在要关闭的代码前一行写上#pragma warning disable 警告代码编码 在要关闭代码行下面一行写上#pragma warning restore 警告代码编码 精准的关闭指定地方引起的代码警告&#xff0c;不会过滤掉无辜的代码 #pragma warning disable 0162,1634HandleL…

JDBC: 连接池

文章目录 没有连接池的现状连接池解决现状问题的原理连接池好处常用连接池的介绍Druid连接池DRUID简介Druid常用的配置参数Druid连接池基本使用API介绍 案例代码 没有连接池的现状 通过下图来分析一下我们目前jdbc程序的结构。 以前使用的jdbc的缺点&#xff1a; 1、操作数据库…

户外打气泵方案软件设计开发

随着户外活动的普及和人们对便捷生活的需求&#xff0c;打气泵成为越来越多有车人士及爱好户外运动的人的装备之一。而打气泵的核心控制是它的芯片和软件方案&#xff0c;今天我们就介绍一下打气泵芯片软件方案的开发过程与技术要点。 打气泵方案的软件设计相较于硬件更具复杂性…

数据库——sql多表查询

当要在两个表&#xff08;或多个表&#xff09;中查找对应数据时&#xff0c;与普通的查询略有不同。本篇博文用于介绍基本的多表查询的方法。 为方便展示&#xff0c;本篇建了两个数据库表“学生表”和“班级表”作为例子 其中&#xff0c;在“学生表”中&#xff0c;cid标签…

RT-DETR改进策略:BackBone改进|CAFormer在RT-DETR中的创新应用,显著提升目标检测性能

摘要 在目标检测领域,模型性能的提升一直是研究者和开发者们关注的重点。近期,我们尝试将CAFormer模块引入RT-DETR模型中,以替换其原有的主干网络,这一创新性的改进带来了显著的性能提升。 CAFormer,作为MetaFormer框架下的一个变体,结合了深度可分离卷积和普通自注意力…

SpringBoot教程(二十四) | SpringBoot实现分布式定时任务之Quartz(动态新增、修改等操作)

SpringBoot教程&#xff08;二十四&#xff09; | SpringBoot实现分布式定时任务之Quartz&#xff08;动态新增、修改等操作&#xff09; 前言数据库脚本创建需要被调度的方法创建相关实体类创建业务层接口创建业务层实现类控制层类测试结果 前言 我这边的SpringBoot的版本为2…

Android 防止截屏和录屏

通过给当前的window对象设置标记WindowManager.LayoutParams.FLAG_SECURE来防止截屏和录屏 protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 防止截屏getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManage…

vscode配置:启用括号对着色

想要的效果&#xff1a;启用括号对着色&#xff0c;在大括号之间用折线表示&#xff0c;看起来会更加直观方便&#xff0c;例如在less中嵌套层级比较多时&#xff0c;大括号的层级不容易看清楚&#xff0c;做了这个配置会更好一些。 vscode安装扩展插件&#xff1a;Bracket P…

Spring Boot学习资源库:Spring生态的精华

摘 要 社会的进步&#xff0c;教育行业发展迅速&#xff0c;人们对教育越来越重视&#xff0c;在当今网络普及的情况下&#xff0c;教学模式也开始逐渐网络化&#xff0c;各大高校开始网络教学模式。 本文研究的教学资源库系统基于Springboot框架&#xff0c;采用Java技术和MYS…

Linux deepin系统通过编辑crontab来设置定时任务---定时关机

在Linux系统中&#xff0c;crontab 是用来设置周期性被执行的指令的守护进程。通过编辑 crontab&#xff0c;您可以安排定时任务&#xff0c;比如定时关机、定时备份文件、定时运行脚本等。以下是如何编辑 crontab 来设置定时任务的步骤&#xff1a; 打开终端&#xff1a;您可以…

AcWing 802. 区间和(离散化算法,python)

本篇博客详细讲解一下离散化知识点&#xff0c;通过讲解和详细列题带大家掌握离散化。 题目&#xff1a; 原题链接&#xff1a;https://www.acwing.com/problem/content/description/804/ 假定有一个无限长的数轴&#xff0c;数轴上每个坐标上的数都是 0。 现在&#xff0c;…