5. 最长回文子串

news2025/1/15 16:43:25

题目描述

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:

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

示例 2:

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

解题思路

最近在学习左成云大神的动态规划解题思路:暴力递归—>记忆化搜索–>动态规划。对于不容易直接推导出动态规划状态转移方程的题,通过暴力递归尝试到最终的动态规划,理解起来比较清晰,尤其是状态方程的转移过程。

暴力递归

  1. 对于回文子串其有一个性质,如果一个字符串S是回文串,那么将S的首尾两个字母去掉剩下的字符串任然是一个回文串
  2. 可以通过递归的方式判断一个字符串是不是回文串。定义递归方程process(char[] str, int L, int R):如果str[L,R]是一个回文串,返回true,否则返回false,
  3. 递归终止条件
    1. 如果L==R,只有一个字符,一定是回文串,返回true
    2. 如果R-1==L,有两个字符
      1. 如果str[L] == str[R],则这两个字符串一定是回文串,返回true
      2. 否则false
/**
 * @param str
 * @param L 左边界
 * @param R 有边界
 * @return 判断str[L,R]是否为一个回文串
 */
public static boolean process(char[] str, int L, int R) {
    if (L == R) {
        return true;
    }
    if (R - 1 == L) {
        return str[L] == str[R];
    }

    if (process(str, L + 1, R - 1)) {//如果str[L+1,R-1]是一个回文串
        if (str[L] == str[R]) {//首尾两个字符相等,显然str[L,R]也是一个回文串
            return true;
        } else {
            return false;
        }
    } else {//str[L+1,R-1]不是一个回文串,那么str[L,R]更不是一个回文串
        return false;
    }
}

通过上述的递归方程,可以求出所有的str所有的字串是否是一个回文串,接下来可以通过记忆化搜索将所有的字串是否为回文串记录下来

记忆化搜索

记忆化搜索主要是用来优化递归过程的,如果有大量的重复过程,通过数组保存已经计算过的递归过程,下次在遇到该递归过程,可以直接返回记录下的值
对于递归函数process(char[] str, int L, int R),三个参数只有L和R两个是变化的,所有可以通过一个二维数组dp[L][R]来记录本次递归的返回值
即dp[L][R]=process(char[] str, int L, int R)

  1. dp的初始值
    dp数组的初始值可由递归终止条件得出
    1. 如果L==R,只有一个字符,一定是回文串,返回true
      即dp[L][L]= true,
    2. 如果R-1==L,有两个字符
      1. 如果str[L] == str[R],则这两个字符串一定是回文串,返回true
        即dp[L][R+1] = true
      2. 否则false
        即dp[L][R+1]=false
        代码实现如下:
      int N = str.length;
      boolean dp[][] = new boolean[N][N];
      dp[N - 1][N - 1] = true;
      for (int i = 0; i <= N - 2; i++) {
          dp[i][i] = true;
          dp[i][i+1]=str[i]==str[i+1];
      }
      
    以字符串str="babad"为例:dp数组的初始值为下图标出的两条对角线:
    在这里插入图片描述
    有了初始值,就可以推导出dp数组的状态转移,状态转移过程由递归函数得出
if (process(str, L + 1, R - 1)) {
    if (str[L] == str[R]) {
        return true;
    } else {
        return false;
    }
} else {
    return false;
}

由上述代码可知,从process(str,L,R)会进入process(str,L+1,R-1)中,其中process(str, L + 1, R - 1)可以用dp[L+1][R-1]表示,即dp[L][R]依赖于dp[L+1][R-1]

if (dp[L + 1][R - 1]) {
    if (str[L] == str[R]) {
        dp[L][R] = true;
    } else {
        dp[L][R] = false;
    }
}else {
    dp[L][R]=false;
}
return dp[L][R]

在这里插入图片描述
即问号处的值依赖于左下角箭头指向的值,所有如果想要得出所有的dp数组值,可以从最下面一行从左到右,然后再从上面一行从左到右依次填dp数组,一直到第一行,就可以得出所有的值

动态规划求解

通过上述可以得出所有dp数组值,也就知道了str的所有字串str[L,R]是否为回文串,最后记录最长的回文子串即可
AC代码

public class Solution {
  public static String longestPalindrome(String s) {
        char[] str = s.toCharArray();
        int N = str.length;
        boolean dp[][] = new boolean[N][N];
        int Left = 0;//最长字串的左边界
        int maxLength =1;//最长字串的长度
        //初始值
		dp[N - 1][N - 1] = true;
        for (int i = 0; i <= N - 2; i++) {
            dp[i][i] = true;
            if (str[i] == str[i+1]){
                if (maxLength<2){
                    Left = i;
                    maxLength = 2;
                }
                dp[i][i + 1] = true;
            }else {
                dp[i][i+1]=false;
            }
        }	
        int maxTem;
        //从下往上,从左往右推
        for (int L = N - 3; L >= 0; L--) {
            for (int R = L+2;R<N;R++){
                if (dp[L+1][R-1]){
                    if (str[L]== str[R]){
                        dp[L][R]=true;//是回文串
                        maxTem = R-L+1;//回文串的长度
                        if (maxLength<maxTem){
                            Left = L;
                            maxLength = maxTem;
                        }
                    }else {
                        dp[L][R] = false;
                    }
                }else {
                    dp[L][R] = false;
                }
            }
        }
        return new String(str,Left,maxLength);
    }
}

通过这种由递归到记忆化搜索,最后到动态规划的过程,可以比较直观的得出问题的解。再某些递归方程不容易推导出,可以通过暴力递归进行尝试,最后改为动态规划

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

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

相关文章

Redis集群系列四 —— 哨兵集群搭建

准备实例和配置 搭建一个三节点的 Sentinel 集群&#xff0c;来监管之前的 Redis 主从集群&#xff0c;如图&#xff1a; 参考上述配置&#xff0c;分别复制 redis 下的 sentinel.conf 文件&#xff0c;如图&#xff1a; 文件中除端口外&#xff0c;其它配置都是一样的。 启动…

路由与交换期末复习整理

一、前言 本文是对前期在校内学习路由与交换课程时对相关知识点的整理&#xff0c;供期末复习参考。 二、选择题知识点 1. 启动配置保存的位置 NVRAM 2. 路由器的功能 网络连接功能、&#xff08;数据处理&#xff09;和设备管理功能。 3. 打开路由器接口的命令 int加接口…

骨骼与绑定

文章目录Blender里的三种绑定.主从绑定.进行物体绑定.进行顶点绑定.解除绑定.保持变换.无反向.进行晶格绑定.约束.变换约束.复制位置.复制旋转.复制缩放.限定距离.限定位置&#xff0c;限定旋转&#xff0c;限定缩放.维持体积.变换.追踪约束.钳制到.阻尼追踪.锁定追踪.拉伸到.标…

【Go基础】初识Go语言

文章目录1. 开发环境搭建2. 第一个Go程序3. Go命令介绍1. 开发环境搭建 在 https://studygolang.com/dl 上下载需要的Go稳定版本&#xff0c;这里我选择的是17.5的版本对于Windows和macOS用户&#xff0c;直接双击即可安装&#xff0c;留意一下安装路径&#xff1b;对于Linux用…

loop为true, slidesPerView为多个的时候,swiper精准获取激活的索引

效果图如下&#xff1a; 重点代码如下&#xff1a; <script>var swiper new Swiper(.swiper-container, {slidesPerView: 3, //显示几个slidespaceBetween: 30, //slide之间的间距centeredSlides: true,loop: true, //开启循环滚动initialSlide: 0, //默认就是0p…

多目标跟踪

目录 多目标跟踪定义&#xff1a; 多目标跟踪分类 多目标跟踪难点分析 多目标跟踪数据集 多目标跟踪评价指标 多目标跟踪定义&#xff1a; 多目标跟踪旨在将视频序列中感兴趣的目标检测出来&#xff0c;并赋予每个目标单独的编号&#xff0c;在整个序列中形成目标的轨迹。 …

BindingException异常的产生原因及解决过程详解

一. 问题背景 今天我在讲完MyBatis后&#xff0c;学生在进行代码练习时遇到了下面这样的一个异常&#xff0c;先上图&#xff1a; 二. 问题分析 1.原因分析 首先我们看到&#xff0c;这里抛出的异常是org.apache.ibatis.binding.BindingException&#xff0c;接着再看异常的…

如何提高外贸客户回复率

业务员接到的每一笔订单都是客户对他的信任&#xff0c;所以合作的前提是信任。如何让客户信任我们或者快速信任我们&#xff0c;尤为关键。 如何提高客户的回复率&#xff0c;米贸搜整理如下: 1.及时回复: 无论是客户发来的询盘还是网上咨询&#xff0c;都要尽快回复客户&am…

Uber应用分享 | 使用 Parquet Page Index 加速 Presto 查询

当前&#xff0c;数据量呈快速增长态势&#xff0c;给诸如 Presto 等查询引擎带来了挑战。Presto 作为一种流行的交互式查询引擎&#xff0c;具有可扩展、高性能并可与 Hadoop 进行平滑集成的特性。随着数据量的增长&#xff0c;Presto 需要读取更大的数据块并将其加载到内存中…

CREAL:为什么光场+HOE是AR眼镜未来

利用光场显示技术&#xff0c;CREAL曾展示出可自然变焦的3D显示效果。为了验证该技术在AR和VR场景的应用&#xff0c;该公司分别打造了两款头显原型。头显对于VR来讲比较常见&#xff0c;但对于AR来讲&#xff0c;眼镜形态才是未来的发展方向。因此&#xff0c;为了缩减AR硬件的…

Unity_IL2CPP常见问题分析

Unity 打包il2cpp模式时的常见问题分析 Unity 编辑器模式下是采用.net 虚拟机解释执行.net 代码&#xff0c;发布的时候有两种模式&#xff0c;一种是mono虚拟机模式&#xff0c;一种是il2cpp模式。由于iOS AppStore规定不允许使用虚拟机&#xff0c;所以发布到iOS,Unity采用了…

推出Linux操作系统Inspur KOS,浪潮信息意欲何为?

2020年底&#xff0c;CentOS突然宣布CentOS7、8等系列版本停止维护的时间表&#xff0c;业界为之震动。 一直以来&#xff0c;Linux都是服务器操作系统市场的顶流支柱。CentOS发行版生命周期的突然变动&#xff0c; 不仅促使很多行业用户思考&#xff1a;“CentOS停止维护之后…

第三十三章 数论——组合数详解(2)

一、组合数——卢卡斯定理 1、问题 这道题中&#xff0c;a,ba,ba,b的范围都是很大的&#xff0c;我们就无法直接用到之前所讲解的预处理阶乘的方法。 如果大家没有看过作者写的组合数&#xff08;1&#xff09;的话&#xff0c;建议大家先去看一下&#xff0c;今天所讲的问题…

【小程序】微信小程序获取头像、呢称2013年最新解决方案(已解决)

一、效果 二、wxml代码 <!-- 点击头像获取头像 --> <view style"margin-bottom: 20px;text-align: center;">---- 点击头像获取logo ----</view> <view class"logo"><button style"width: 100px;height:100px;" cla…

易诚互动在创业板更新招股书:上半年出现亏损,极其依赖阿里云

12月27日&#xff0c;北京易诚互动网络技术股份有限公司&#xff08;下称“易诚互动”&#xff09;在深圳证券交易所更新招股书&#xff0c;准备在创业板上市。本次冲刺上市&#xff0c;易诚互动计划募资3.13亿元&#xff0c;将用于用于数字银行应用平台升级项目、大数据智能风…

问题解决丨对不起,小米路由器出现网络连接问题无法打开网页

之前Chrome浏览器一直用的好好的&#xff0c;不过最近出现以下问题 “对不起&#xff0c;小米路由器出现网络连接问题无法打开网页”。 奇怪的是&#xff0c;使用Edge浏览器可以正常访问网页&#xff0c;但是Chrome会不行&#xff0c;每次如果要正常访问需要关闭所有Chrome的…

迭代次数的隐约脚印

( A, B )---1*30*2---( 1, 0 )( 0, 1 ) 继续一维的实验&#xff0c;这次区别是A和B都由5个点构成。 A B 迭代次数&#xff08;7e-4&#xff09; 0 0 0 0 0 1 1 1 0 1 1b 1b 1b 0 1b 0*0*0*0*0-1*1*1*0*1 22047.98995 如A为00000&#xff0c;B为11101&#…

外贸网站优化与外贸网页优化的区别

对于大多数外贸企业和个人站长来说&#xff0c;网页优化是非常重要的&#xff0c;但是说到网站优化&#xff0c;很多人会有一个误区&#xff0c;就是经常把网站优化和搜索引擎优化混为一谈。虽然两者之间有很多重叠的地方&#xff0c;但是如果再细分的话&#xff0c;两者还是有…

JSP ssh 物流信息管理系统myeclipse开发oracle数据库MVC模式java编程计算机网页设计

一、源码特点 JSP ssh 物流信息管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用 B/S模式开发。开发环境为TOMCAT7.…

专业低代码平台应该具备什么?

编者按&#xff1a;低代码火爆的同时&#xff0c;很多低代码平台如雨后春笋般涌出&#xff0c;那么一个真正的专业低代码平台应该具备什么特性呢&#xff1f;本文将为你剖析老厂商天翎低代码平台的特点&#xff0c;一起感受低代码平台的魅力。 关键词&#xff1a;读写分析&…