最长回文子串:动态规划推导

最长回文子串:结合图形推导动态规划

题目介绍

本题可以在力扣找到,题号为5。
给你一个字符串 s,找到 s 中最长的 回文子串。

示例 1:

输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:

输入:s = “cbbd”
输出:“bb”

提示:

1 <= s.length <= 1000
s 仅由数字和英文字母组成

暴力解法

先从暴力解法入手,对于长度为n的字符串,总共有 (n+1) * n / 2 种组合,我们可以找出每种组合,然后判断其是否是回文串,最后与当前的最大值进行比较,若新串更大,就更新答案。

我们先写一个判断回文串的函数,用双指针判断即可:

    public static boolean isPalindrome(String s) {int left = 0;int right = s.length() - 1;while (left < right) {if (s.charAt(left) != s.charAt(right)) {return false;}left++;right--;}return true;}

然后我们用双重循环,遍历到每一种可能,在进行进一步判断:

class Solution {public String longestPalindrome(String s) {String resp = "";int ans = 0;int[][] dp = new int[s.length()][s.length()];int n = s.length();for (int i = 0;i < n;i++) {for (int j = i;j < n;j++) {//获取子串String subString = s.substring(i,j+1);//判断是否要更新最长子串if (subString.length() > resp.length() && isPalindrome(subString)) {resp = subString;}}}//返回答案return resp;}public boolean isPalindrome(String s) {int left = 0;int right = s.length() - 1;while (left < right) {if (s.charAt(left) != s.charAt(right)) {return false;}left++;right--;}return true;}
}

动态规划

接下来我们可以考虑动态规划的解法,所谓动态规划,就是用之前的状态递推后面的状态。首先我们需要确定一个状态转移条件,对于一个 字符串 来说,如果有 一个子串str 为回文串,且 str的前一个字符和后一个字符也相同(比如说 “aba” 和 “aabaa”)那么就说明 [str-1,str+1] 也为回文串。我们可以定一个二维数组,将其定义为 从 i 到 j 的子串是否是回文串:

//初始化一个状态数组--布尔类型
int[][] dp = new int[n][n];
for (int i = 0;i < n;i++) {//对于单个字符的情况,必定为回文串dp[i][i] = true;
}

根据我们之前的结论,可以推出状态转移方程,即

if (s.charAt(i) == s.charAt(j) && dp[i+1][j-1] == true) {dp[i][j] = true;
} else {dp[i][j] = false;
}

可以看到,dp[i][j]的状态是基于 dp[i+1][j-1]的,即若要得到 dp[i][j],则要先得到dp[i+1][j-1]的状态,光这么描述其实还是很抽象,我们借助矩阵图来理解:
在这里插入图片描述
我们把横轴作为j,纵轴作为i,首先我们可以填充 dp[i][i],即只有一个字符的情况,都可以填充为true:
在这里插入图片描述
其次,对于j > i 的情况其实都可以不用考虑,因为起始位置是要始终小于结束位置的:
在这里插入图片描述
接着,我们推到一般情况的依赖关系,我们先任选一点,比如 dp[0][2],根据状态转移方程,我们需要参考的就是 dp[1][1] 的状态值了:
在这里插入图片描述
即,对于每一个状态,在二位图像上总是需要依赖其左下角的具体状态,所以理论上来说,只要从对线向右上填充,我们就可以得到整个dp数组的状态了:
在这里插入图片描述
对于上面的示例来说,只要我们填充了 i = j 以及 i + 1 = j 这两条对角线,我们就可以成功推导出整个dp数组的状态,接下来我们开始编程实现:

    public static String longestPalindrome(String s) {int n = s.length();boolean[][] dp = new boolean[n][n];//填充对角线for (int i = 0;i < n;i++) {dp[i][i] = true;}//填充 j = i + 1for (int i = 0;i < n-1;i++) {int j = i + 1;if (s.charAt(i) == s.charAt(j)) {dp[i][j] = true;}}//填充其余情况,按对角线顺序填充for (int offset = 0;offset < n-2;offset++) {for (int i = 0;i < n-2-offset;i++) {int j = i + 2 + offset;if (s.charAt(i) == s.charAt(j) && dp[i+1][j-1]) {dp[i][j] = true;}}}//遍历dp数组,求出最长值int longestLength = 0;String resp = "";for (int i = 0;i < n;i++) {for (int j = 0;j < n;j++) {if (dp[i][j] && j - i + 1 > longestLength) {longestLength = j - i + 1;resp = s.substring(i,j+1);}}}return resp;}

具体实现就如上,需要注意的是,由于 dp[i][j] 依赖于 dp[i+1][j-1],即依赖于左下角的状态,所以我们填充一般状态的时候也需要按照这个顺序填充,即需要按照对角线层层填充才能得到正确答案。

我们可以与暴力做法的耗时作比较,暴力解法耗时大概在 1000ms左右,而上面这种基于动态规划的解法耗时只有 200ms左右:
在这里插入图片描述
大幅优化了耗时,不过上述解法中还有可以改进的地方,比如我们可以在填充dp数组的时候就开始寻找答案,而不是分两步走:

    public static String longestPalindrome(String s) {int n = s.length();boolean[][] dp = new boolean[n][n];//填充对角线for (int i = 0;i < n;i++) {dp[i][i] = true;}int longestLength = 1;String resp = s.charAt(0) + "";//填充 j = i + 1for (int i = 0;i < n-1;i++) {int j = i + 1;if (s.charAt(i) == s.charAt(j)) {dp[i][j] = true;if (j - i + 1 > longestLength) {longestLength = j - i + 1;resp = s.substring(i,j+1);}}}//填充其余情况,按对角线顺序填充for (int offset = 0;offset < n-2;offset++) {for (int i = 0;i < n-2-offset;i++) {int j = i + 2 + offset;if (s.charAt(i) == s.charAt(j) && dp[i+1][j-1]) {dp[i][j] = true;//将判断步骤放入填充步骤中if (j - i + 1 > longestLength) {longestLength = j - i + 1;resp = s.substring(i,j+1);}}}}return resp;}

这样我们就可以省去一次遍历的开销,最终优化效果到 139ms 左右:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI引擎点燃消费电子市场,有芯片企业利润飙涨至792.79%!

导语 这一市场出现回暖&#xff01;多家芯片企业净利润增长。 好消息&#xff01;消费电子在经历两年低谷期后&#xff0c;终于迎来了拐点。 根据中国通信院发布的数据显示&#xff0c;1—6月&#xff0c;国内市场手机出货量1.47亿部&#xff0c;同比增长13.2%&#xff1b;智能…

低代码门户技术:赋能业务灵活性与创新的新时代

随着数字化转型的深入推进&#xff0c;各行各业对灵活、高效的技术解决方案的需求日益增长。在这个背景下&#xff0c;低代码门户技术应运而生&#xff0c;为企业提供了一种新颖的应用开发方式。今天&#xff0c;我们将探讨低代码门户技术的基本概念、优势以及如何在实际应用中…

Ubuntu 24.04 上安装和配置 Zabbix Agent

Zabbix 是一个强大的开源监控工具&#xff0c;可以帮助您跟踪服务器&#xff0c;网络和应用程序。在主机环境中配置了 Zabbix Server 之后&#xff0c;下一步是添加用于监视的远程主机。Zabbix Agent 从您的服务器收集数据并将其发送到 Zabbix 服务器进行监控。 本指南将向您展…

three.js渲染中文的3D字体

下载中文字体 引入下面的代码 点击下载 提取码: lywa <!DOCTYPE html> <html lang"en"><head><title>three.js webgl - modifier - tessellation</title><meta charset"utf-8"><meta name"viewport" c…

chapter08-面向对象编程——(章节内容梳理)——day10

目录 快捷键 访问修饰符 封装 继承 方法重写 多态 快捷键 访问修饰符 封装 继承 本质 方法重写 多态 编译类型、运行类型、动态绑定机制

如何下载西门子电气元件EPLAN EDZ文件以及CAD文件等?

如何下载西门子电气元件EPLAN EDZ文件以及CAD文件等? 西门子全球电子商务: https://mall.industry.siemens.com/goos/WelcomePage.aspx?regionUrl=/cn&language=zh 西门子Industry Image Database: https://www.automation.siemens.com/bilddb/index.aspx?lang=en 以…

【Scala】Windows下安装Scala(全面)

1.下载 官网下载地址&#xff1a;https://downloads.lightbend.com/scala/2.11.12/scala-2.11.12.msi 2.安装 双击下载的.msi文件&#xff1a; 勾选"I accept the terms in the License Agreement",然后点击下一步 修改自己的安装路径&#xff1a; 然后选择brow…

快讯 | Midjourney开拓硬件领域:苹果前经理加盟助力发展

硅纪元快讯栏目&#xff0c;每日追踪AI领域的最新动态&#xff0c;快速汇总最新科技新闻&#xff0c;助您时刻紧跟行业趋势。简明扼要的呈现资讯概要&#xff0c;让您快速了解前沿资讯。 1分钟速览新闻 Claude AI 聊天机器人性能下滑引争议 中国能源化工行业首个330亿参数昆仑…

vagrant 创建虚拟机

创建一个名为 “Vagrantfile” 的文件&#xff0c;修改如下内容&#xff1a; Vagrant.configure("2") do |config|(1..3).each do |i|config.vm.define "k8s-node#{i}" do |node|# 设置虚拟机的Boxnode.vm.box "centos/7"# 设置虚拟机的主机名…

大模型时代,算法工程师的黄金时代

在大模型时代&#xff0c;算法工程师的角色已经超越了传统的编程和算法优化&#xff0c;他们成为了推动技术革新和业务发展的关键力量。作为一名算法工程师&#xff0c;我深刻地感受到这个时代对我们的新要求和期待。回想起我刚刚踏入这个领域时&#xff0c;深度学习还只是少数…

一文全面了解机房动环监控系统/机房环控方案@卓振思众

机房动环监控是一个综合的动力与环境监控系统&#xff0c;主要用于确保机房设备和环境的稳定运行。机房动环监控作为保障数据中心正常运行的重要系统&#xff0c;其重要性不言而喻。在当前信息化、数字化时代背景下&#xff0c;各种业务的数字化转型要求数据中心必须具备高度的…

九盾安防提供的叉车警报灯蜂鸣器

随着物流行业的快速发展&#xff0c;叉车作为重要的物料搬运设备&#xff0c;其安全性日益受到重视。叉车警报灯蜂鸣器作为一种重要的安全装置&#xff0c;能够有效提醒操作人员和周边人员注意叉车动向&#xff0c;避免潜在的安全隐患。因此&#xff0c;市场需求量逐年上升&…

偷偷用了这10款AI写作神器,再也没加过班!

前言 [ 自2022年Chat-GPT在全球掀起AI革命浪潮&#xff0c;AI开始在内容的生产方式进行颠覆性改变。 其中&#xff0c;AI写作工具的崛起&#xff0c;为内容创作者打开了一个全新创作世界&#xff0c;无论用户在办公写作、自媒体写作还是兴趣写作&#xff0c;在效率方面都得到…

开学季有什么必买好物?2024数码好物清单大合集!

随着新学期的到来&#xff0c;相信很多学生都在准备迎接新的挑战和机遇。在这个充满活力的开学季&#xff0c;为了更好地适应学习和校园生活&#xff0c;挑选一些实用又高效的数码好物是非常必要的。不仅可以提高学习效率的工具&#xff0c;还可以提升生活质量&#xff0c;接下…

商用车ADAS风口再起!极目智能发布行业首款商用车舱驾一体域控

商用车ADAS相关强制法规再升级&#xff0c;新一轮技术方案迭代周期已然来临。 2024年5月&#xff0c;交通部陆续发布针对AEBS的征求意见稿(JT/T1178.1/1178.2/1285/1094)&#xff0c;要求所有3.5吨以上的营运车辆强制安装AEBS系统&#xff0c;该意见稿预计2024年年底发布。 今…

16002.orin nano平台 linux gpio 学习记录

文章目录 1 查看当前系统gpio配置信息2 orin / nano gpio2.1 GPIO 映射表2.2 nano 平台对外提供的2排端口表 3 配置GPIO 电平3.1 通过指令配置普通GPIO高电平3.2 通过设备树配置普通GPIO高电平3.3 配置特定 gpio 高电平 1 查看当前系统gpio配置信息 sudo cat /sys/kernel/debu…

FPGA实现HDMI传输(二)

之前的文章简单介绍了HDMI接口、TMDS编码以及ADV611工作原理和寄存器配置&#xff0c;本篇博客将给出具体的代码以及板级验证结果&#xff0c;代码参考自米联客的教程。 一.ADV7611配置 1.i2c驱动模块 timescale 1ns / 1psmodule uii2c# (parameter WMEN_LEN …

JVM对象创建和内存分配机制深度解析

一、对象创建方式 1、new关键字 这是最常见的创建对象的方式。通过调用类的构造方法&#xff08;constructor&#xff09;来创建对象。如&#xff1a;MyClass obj new MyClass()。这种方式会触发类的加载、链接、初始化过程&#xff08;如果类还未被加载过的话&#xff09;&…

ComfyUI SDXL Prompt Styler 简介

SDXL Prompt Styler 来自于 comfyui-art-venture 节点 style 已经更新 旧版本的 sai-line art 变更为 line art log_prompt 已经更新 旧版本的 false 变更为 Yes 或 No style_name 已经更新 旧版本的 true &#xff08;不再适用&#xff09;&#xff08;可以尝试对应style中…

亲测好用,ChatGPT 3.5/4.0新手使用手册,最全论文指令手册~ 【2024年9月 更新】

本以为遥遥领先的GPT早就普及了&#xff0c;但小伙伴寻找使用的热度一直高居不下&#xff0c;其实现在很简单了&#xff01; 国产大模型快200家了&#xff0c;还有很多成熟的国内AI产品&#xff0c;跟官网一样使用&#xff0c;还更加好用~ ① 3.5 大多数场景是够用的&#xff…