算法系列--动态规划--回文子串系列

💕"我们好像在池塘的水底,从一个月亮走向另一个月亮。。"💕
作者:Mylvzi
文章主要内容:算法系列–动态规划–回文子串系列
在这里插入图片描述

今天为大家带来的是算法系列--动态规划--回文子串系列(1),本文重点掌握如何快速判断一个字符串是否是回文子串

一.回文子串(引入)

先来看力扣上这道题目:回文子串

在这里插入图片描述

1.利用动态规划的思想解决这道题目(重点)

回文子串其实是子数组的一种,只不过这里将数字换为字符而已,所以回文子串的问题也可以使用动态规划的思想解决,但是这个状态表示相较于常规的字符数组有些不同,在回文子串问题中,我们需要创建一个二维的dp表去存储所有子串是否是回文子串的信息,也就是说这个dp表是一个`boolean``类型的数组

首先如何得到所有的子字符串呢?很简单,两层for循环就能解决这个问题
在这里插入图片描述
注意:单独一个字符也算子字符串!!!

明确上述前置知识之后,下面讲解如何利用动态规划的思想解决回文子串问题

  1. 状态表示:dp[i][j]表示以i下标为起始位置,j下标为结束位置的子字符串是否是回文子串的信息

  2. 状态转移方程:
    在这里插入图片描述

  3. 初始化:无需初始化,越界的条件被特别判断了,不会出现越界的情况
    在这里插入图片描述

  4. 填表顺序:从下往上填
    在这里插入图片描述

  5. 返回值:dp[i][j]为true的数目

代码实现:

class Solution {
    public int countSubstrings(String s) {
        char[] ss = s.toCharArray();// 转化为字符数组
        int ret = 0;// 记录dp表中true的数目

        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(ss[i] == ss[j])// 只用判断相等的情况,不相等就是默认值false;
                    dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
                ret += dp[i][j] == true ? 1 : 0;
            }
        }

        return ret;
    }
}

如果使用动态规划,时间复杂度,空间复杂度均为为O(N^2)回文子串问题使用动态规划虽然不是最优解,但是可以实现一个非常重要的功能将所有子串是否是回文子串的信息,存储到dp表之中,最优解还有中心拓展算法马拉车算法

中心拓展算法的实现:

链接:https://leetcode.cn/problems/palindromic-substrings/solutions/379987/hui-wen-zi-chuan-by-leetcode-solution/
来源:力扣(LeetCode)

class Solution {
    public int countSubstrings(String s) {
        int n = s.length(), ans = 0;
        for (int i = 0; i < 2 * n - 1; ++i) {
            int l = i / 2, r = i / 2 + i % 2;
            while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {
                --l;
                ++r;
                ++ans;
            }
        }
        return ans;
    }
}

2.最长回文子串

链接:
https://leetcode.cn/problems/longest-palindromic-substring/

分析:

还是利用和上道题一样的动态规划思想,在本题中需要得到的是最长的回文子串,在回文子串的动态规划里,我们已经保存了所有的回文子串的信息,只要判断出来时回文子串,就更新一下长度即可

可以使用一个数组ret来记录字符串的起始结束位置

代码:

class Solution {
    public String longestPalindrome(String s) {
        char[] ss = s.toCharArray();
        int n = s.length();
        boolean[][] dp = new boolean[n][n];// 创建dp表

        int[] ret = new int[2];// 记录字符串的起始位置和结束位置

        for(int i = n - 1; i >=0; i --){
            for(int j = i; j < n; j++) {
                if(ss[i] == ss[j])
                    dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
                if(dp[i][j] == true) {
                    if(j - i > ret[1] - ret[0]) {
                        ret[0] = i;ret[1] = j;
                    }
                }
            }
        }

        return s.substring(ret[0],ret[1] + 1);// 注意是"左闭右开"
    }
}

3.回⽂串分割IV

链接:
https://leetcode.cn/problems/palindrome-partitioning-iv/description/
在这里插入图片描述

分析:

  • 其实题目的意思很简单,就是判断字符串s能否分割为三个回文子串,最直观的想法就是暴力求解+判断是否是回文子串,而判断是否是回文子串已经在上面做过了
    在这里插入图片描述
    代码:
class Solution {
    public boolean checkPartitioning(String s) {
        char[] ss = s.toCharArray();// 转化为字符数组
        int ret = 0;// 记录dp表中true的数目

        int n = s.length();
        boolean[][] dp = new boolean[n][n];

        // 使用dp表保存所有的子字符串的信息
        for(int i = n - 1; i >= 0; i--) {// 从后往前遍历字符串
            for(int j = i; j < n; j++) {
                if(ss[i] == ss[j])// 只用判断相等的情况,不相等就是默认值false;
                    dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
            }
        }

        // 将字符串s分割为三个子字符串,分别判断是否是回文字符串
        for(int i = 1; i < n - 1; 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

链接:
https://leetcode.cn/problems/palindrome-partitioning-ii/description/
在这里插入图片描述
分析:

其实这道题和单词拆分很像,单词拆分中需要我们遍历整个字符串,判断对应的单词是否存在于字典之中,本题也是需要遍历整个字符串,判断对应的子字符串是否是回文子串,而判断是否是回文子串已经在上面介绍过

在这里插入图片描述

代码:

class Solution {
    public int minCut(String s) {
        char[] ss = s.toCharArray();// 转化为字符数组
        int ret = 0;// 记录dp表中true的数目

        int n = s.length();
        boolean[][] predp = new boolean[n][n];

        for(int i = n - 1; i >= 0; i--) {// 从后往前遍历字符串
            for(int j = i; j < n; j++) {
                if(ss[i] == ss[j])// 只用判断相等的情况,不相等就是默认值false;
                    predp[i][j] = i + 1 < j ? predp[i + 1][j - 1] : true;
            }
        }

        // 下面是正题
        int[] dp = new int[n];
        for(int i = 0; i < n; i++) dp[i] = Integer.MAX_VALUE;// 初始化为最大值

        for(int i = 0; i < n; i++) {
            if(predp[0][i] == true) dp[i] = 0;// 0->i为回文串
            else {// 0->i不是回文串
                for(int j = 1; j <= i; j++) {
                    if(predp[j][i]) dp[i] = Math.min(dp[i],dp[j - 1] + 1);
                }
            }
        }

        return dp[n - 1];
    }
}

5.最长回文子序列

链接:
https://leetcode.cn/problems/longest-palindromic-subsequence/

分析:

最先想到的状态表示就是以i位置为结尾字符串中的最长的回文子序列的长度,但是进一步分析发现此状态表示无法推导出状态转移方程,原因在于我们根本不能确定回文子序列,所以要更换一个状态表示

经过上述分析发现仅仅固定一个位置去表示字符串无法确定其回文子序列,所以需要两个下标来确定一个字符串(是不是和回文子串很像?),然后再去推导状态转移方程,只不过这里的状态相较于连续的子串更多一些,下面是详细的分析过程
在这里插入图片描述

代码:

class Solution {
    public int longestPalindromeSubseq(String s) {

        char[] ss = s.toCharArray();// 转化为字符数组
        int n = s.length();

        // 创建dp表
        int[][] dp = new int[n][n];
        dp[0][0] = dp[n - 1][n - 1] = 1;// 初始化
        int ret = 0;// 记录最大值

        for(int i = n -1; i >=0; i--) {
            for(int j = i; j < n; j++) {
                if(ss[i] == ss[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]);
                }

                ret = ret > dp[i][j] ? ret : dp[i][j];// 更新最值
            }
        }

        return ret;
    }
}

6.让字符串成为回⽂串的最⼩插⼊次数(hard)

链接:
https://leetcode.cn/problems/minimum-insertion-steps-to-make-a-string-palindrome/description/

分析:

在这里插入图片描述

代码:

class Solution {
    public int minInsertions(String s) {
        char[] ss = s.toCharArray();// 转化为字符数组
        int n = s.length();

        // 创建dp表
        int[][] dp = new int[n][n];

        for(int i = n - 1; i >= 0; i--) {
            for(int j = i; j < n; j++) {
                if(ss[i] == ss[j]) dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : 0;
                else dp[i][j] = Math.min(dp[i + 1][j],dp[i][j - 1]) + 1;
            }
        }

        return dp[0][n - 1];
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux相关命令(2)

1、W &#xff1a;主要是查看当前登录的用户 在上面这个截图里面呢&#xff0c; 第一列 user &#xff0c;代表登录的用户&#xff0c; 第二列&#xff0c; tty 代表用户登录的终端号&#xff0c;因为在 linux 中并不是只有一个终端的&#xff0c; pts/2 代表是图形界面的第…

伦敦银操作建议中所蕴含的支撑阻力位技术

在伦敦银操作建议或者报告中&#xff0c;尤其是有关伦敦银操作技术分析的建议中&#xff0c;我们总是能看到一个名词&#xff1a;支撑阻力位。其实支撑阻力位有两个意思&#xff0c;一个是支撑位&#xff0c;一个是阻力位&#xff0c;我们习惯将它们合起来称呼&#xff0c;实际…

uniapp安装axios

先npm安装 npm i axios然后在项目里面建一个utils文件&#xff0c;再建一个index.js 以下是index.js代码&#xff1a; import axios from axios; const service axios.create({baseURL: //xxxx.xxxxx.com///你的请求接口域名, timeout: 6000, // request timeoutcrossDomai…

设计数据库之外部模式:数据库的应用

Chapter5&#xff1a;设计数据库之外部模式&#xff1a;数据库的应用 笔记来源&#xff1a;《漫画数据库》—科学出版社 设计数据库的步骤&#xff1a; 概念模式 概念模式(conceptual schema)是指将现实世界模型化的阶段进而&#xff0c;是确定数据库理论结构的阶段。 概念模…

【 yolo红外微小无人机-直升机-飞机-飞鸟目标检测】

yolo无人机-直升机-飞机-飞鸟目标检测 1. 小型旋翼无人机目标检测2. yolo红外微小无人机-直升机-飞机-飞鸟目标检测3. yolo细分类型飞机-鸟类-无人机检测4. yolo红外大尺度无人机检测 1. 小型旋翼无人机目标检测 类别 nc: 1 names: [‘drone’] 数据集和模型 VOC无人机UAV数据…

小目标检测常见解决策略总结

1. 引言 尽管目标检测算法取得了长足的发展&#xff0c;例如 Faster RCNN、YOLO、SSD、RetinaNet、EfficientDet 等。通常&#xff0c;这些模型是在 COCO数据集上训练的。它是一个包含各种对象类别和标注的大规模数据集&#xff0c;因此在训练对象检测器方面很受欢迎。然而&am…

FEX-Emu在Debian/Ubuntu系统使用

FEX-Emu在Debian/Ubuntu系统使用 1. Debootstrap子系统安装&#xff08;可选&#xff09;2. Debian/Ubuntu依赖包安装3. 获取FEX-Emu源码并编译4. 根文件系统RootFS安装5. 基于 FEX-Emu 运行应用 1. Debootstrap子系统安装&#xff08;可选&#xff09; sudo apt-get install …

蓝桥杯第二天刷真题

public class Main {public static void main(String [] args) { //存大数方法String s"202320232023"; // 定义一个字符串&#xff0c;它将被转换为结束循环的数值long end Long.parseLong(s);long sum 0;long primarynumber 1;for(int i 1; i<end; i) {long …

基于甘特图的资源调度优化策略

资源在项目管理中是一个永恒的话题。无论人力、物力还是财力资源,总是捉襟见肘,都希望用最少的资源完成最大的工作。这就要求我们在资源调度方面果断精准,做到最优化。而甘特图作为项目时间规划的重要工具,恰恰能为资源调度提供绝佳帮助。 甘特图能反映出任务之间的制约关系,有…

liunx CentOS7 搭建lnmp环境 php nginx mysql

安装一些刚需软件&#xff1a;不懂请自行查询 安装一些需要的软件命令 yum install wget vim net-tools bash* lrzsz tree nmapnc lsof telnet -y 刷新命令 source /usr/share/bash-completion/bash_completion echo source /usr/share/bash-completion/bash_completion &…

0-1背包

问题描述 现有4个物品&#xff0c;小偷背包总容量为8&#xff0c;怎么可以偷得价值最多的物品&#xff1f; 物品编号&#xff1a;1 2 3 4 物品重量&#xff1a;2 3 4 5 物品价值&#xff1a;3 4 5 8 输入 …

【Flink】Flink 中的时间和窗口之窗口其他API的使用

1. 窗口的其他API简介 对于一个窗口算子而言&#xff0c;窗口分配器和窗口函数是必不可少的。除此之外&#xff0c;Flink 还提供了其他一些可选的 API&#xff0c;可以更加灵活地控制窗口行为。 1.1 触发器&#xff08;Trigger&#xff09; 触发器主要是用来控制窗口什么时候…

2核2G服务器阿里云多少钱一年?

阿里云2核2G服务器配置优惠价格61元一年和99元一年&#xff0c;61元是轻量应用服务器2核2G3M带宽、50G高效云盘&#xff1b;99元服务器是ECS云服务器经济型e实例ecs.e-c1m1.large&#xff0c;2核2G、3M固定带宽、40G ESSD entry系统盘&#xff0c;阿里云活动链接 aliyunfuwuqi.…

springboot295基于Mysql的商业辅助决策系统的设计与实现

商业辅助决策系统的设计与实现 摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统收支信息和销售订单信息管…

神奇科技突破:瘫痪男子通过Neuralink脑植入物重新掌控数字世界!

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

电子电器架构 —— 诊断数据DTC起始篇(上)

电子电器架构 —— 诊断数据DTC起始篇(上) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再…

iStoreOS R4S软路由结合内网穿透实现公网远程本地电脑桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能&#xff0c;也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…

1.6 学Python能干什么,Python的应用领域有哪些

Python能干什么&#xff0c;Python的应用领域 Python 作为一种功能强大的编程语言&#xff0c;因其简单易学而受到很多开发者的青睐。那么&#xff0c;Python 的应用领域有哪些呢&#xff1f; Python 有着非广泛的应用&#xff0c;几乎所有大中型互联网公司都在使用 Python&a…

海外问卷调查项目是割韭菜吗?

大家好&#xff0c;我是橙河老师&#xff0c;今天聊一聊国外问卷调查挣钱是真实的吗&#xff1f;海外问卷调查项目是割韭菜吗&#xff1f; 作为问卷行业的老司机&#xff0c;我可以很负责的告诉大家&#xff0c;海外问卷调查这个项目是可以做的&#xff0c;我已经做了4年时间&…

基于SpringBoot+Vue信息化在线教学平台的设计与实现(源码+部署说明+演示视频+源码介绍+lw)

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…