20211202完全对称日,我们一起来温习一下

大家好,今天我们来聊一聊最长回文子串这个问题。

前几天,有个校招的小伙伴问到了这个问题。今天,我们就来分析一下。

最长回文子串不论是在校招还是社招中都是各大厂出现频率比较高的题目。所以对于正在找工作的同学来说,这是必须要准备的一道题。

Tips:回文串就是正反读都是一样的字符串,比如”上海自来水来自海上”。

问题描述

给你一个字符串 s,找到s中最长的回文子串。
示例:
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <="1000" s 仅由数字和英文字母(大写和 或小写)组成 code></=>

分析问题

一看到这个问题,我们直接从定义出发,这是最容易想到的解决方案。我们把这个”最长回文子串”这几个字,拆开来看,它的要求有三点:”最长”、”回文”、”子串”。首先它是”子串”,然后再”回文”,最后是”最长”。所以,这就很容易理解了,我们把所有的子串求出来,然后判断是不是”回文”,把最长的”回文”拿过来,这个问题不就迎刃而解了。想通这个逻辑,那代码写起来就简单多了。下面我们来看看代码如何实现。

def isPalindromic(ss):
    n=len(ss)
    for i in range(int(n/2)):
        if(ss[i]!=ss[n-i-1]):
            return False
    return True

def longestPalindrome(s):
    ans=""
    maxlen=0
    n=len(s)
    #&#x6C42;&#x51FA;&#x6240;&#x6709;&#x5B50;&#x4E32;
    for i in range(n):
        for j in range(i+1,n):
            ss=s[i:j]
            #&#x5224;&#x65AD;&#x5B50;&#x4E32;&#x662F;&#x5426;&#x662F;&#x201C;&#x56DE;&#x6587;&#x201D;
            if(isPalindromic(ss)):
                #&#x62FF;&#x51FA;&#x6700;&#x957F;&#x7684;
                if(len(ss)>maxlen):
                    ans=ss
                    maxlen=len(ss)
    return ans

print(longestPalindrome("cbbd"))

这个算法的实现复杂度是O(n^3),空间复杂度是O(1)。那我们有什么优化方式来降低时间复杂度吗?

优化

既然你正反读是一样的,我们把原字符串翻转生成一个新的字符串,然后拿新的字符串和原字符串求最长公共子串不就可以了吗?那我们如何求两个字符串的最长公共子串呢?既然要找公共子串,那不就是求出两个字符串的所有子串,然后比较他们是否相同,找出最长的相同的子串。显而易见,这个算法的时间复杂度也是O(n^3),这不和上面那个算法复杂度一样吗?也没优化上啊。

def longestCommonSubstring(s1,s2):
    n1=len(s1)
    n2=len(s2)
    maxlen=0
    ans=""
    for i in range(n1):
        for j in range(n2):
            length=0
            m=i
            n=j
            while m<n1 and n<n2: if s1[m]!="s2[n]:" break m="m+1" n="n+1" length="length+1"> maxlen:
                maxlen=length
                ans=s1[i:i+maxlen]
    return ans
</n1>

不要着急,我们慢慢往下看。可以先喝口茶休息休息。

有了上面的这个解答,面试官肯定是不满意嘛。要想拿到offer,我们还得加把劲。

我们来看上面的解答有哪些问题呢?我们可以知道在进行子串比较的过程中,多了很多重复的比较。也就是代码里的while循环部分。比如我们在比较以i和j分别为起点的子串时,有可能会进行 i+1j+1以及 i+2j+2位置的字符的比较。而在比较以 i+1 &#x548C;j+1分别为起始点字符串时,这些字符又会被比较一次了。这就说明了该问题有”重叠子问题”的特征,那我们是不是可以用动态规划来解决呢?

我们假设两个字符串分别为s和t,s[i]和t[j]分别表示第i和第j个字符。我们用a[i] [j]表示以s[i]和t[j]为结尾的相同子串的最大长度。那我们就可以很容易推导出a[i+1] [j+1]之间的关系,这两者之间就差a[i+1]和t[j+1]这一对字符,如果a[i+1]和t[j+1]相等,那么a[i+1] [j+1]=a[i] [j] +1,如果不相等,则a[i+1] [j+1]=0。当i=0或者j=0时,对应字符相等的话a[i] [j]=1,不相等的话,则为0。下面,我们来看一下代码如何实现。

def longestPalindrome(s):
    if s=="":
        return ""
    #&#x5B57;&#x7B26;&#x4E32;&#x53CD;&#x8F6C;
    t=s[::-1]
    n=len(s)
    a=[[0 for _ in range(n)] for _ in range(n)]
    maxlen=0
    maxend=0
    for i in range(n):
        for j in range(n):
            if(s[i]==t[j]):
                if i == 0 or j == 0:
                    a[i][j]=1
                else:
                    a[i][j]=a[i-1][j-1]+1

            if a[i][j] > maxlen:
                maxlen=a[i][j]
                #&#x4EE5;i&#x4E3A;&#x7ED3;&#x5C3E;&#x7684;&#x5B50;&#x4E32;
                maxend=i

    return s[maxend-maxlen+1:maxend+1]

我们来看下面这个例子S1=”abcedcba”,S2=”abcdecba”。最长的公共子串是”abc”和”cba”,但很明显这不是回文子串。所以,我们在求出最长公共子串后,还需要判断一下该子串倒置前后的下标是否相匹配。比如S1=”daba”,S2=”abad”。S2中aba的下标是0,1,2,倒置前是3,2,1,和S1中的aba的下标符合,所以aba是最长回文子串。其实,我们不需要每个字符都判断,我们只需要判断末尾字符就可以了。

20211202完全对称日,我们一起来温习一下

如图所示,我们来看最长公共子串”aba”在翻转前后末尾字符”a”对应的下标分别为i和j。翻转字符串t中该子串的末尾字符”a”对应的下标是j=2,在翻转前s中对应的下标为m=length-1-j=4-1-2=1。m对应的是公共子串在原字符串s中首位字符的下标,再加上子串的长度,即m+a[i] [j]-1对应的是公共子串在原字符串s中末尾字符的下标,如果它和i相等,则说明该子串是回文子串。下面,我们来看一下代码的实现。

def longestPalindrome(s):
    if s=="":
        return ""
    #&#x5B57;&#x7B26;&#x4E32;&#x53CD;&#x8F6C;
    t=s[::-1]
    n=len(s)
    a=[[0 for _ in range(n)] for _ in range(n)]
    maxlen=0
    maxend=0
    for i in range(n):
        for j in range(n):
            if(s[i]==t[j]):
                if i == 0 or j == 0:
                    a[i][j]=1
                else:
                    a[i][j]=a[i-1][j-1]+1

            if a[i][j] > maxlen:
                #&#x7FFB;&#x8F6C;&#x524D;&#x5BF9;&#x5E94;&#x7684;&#x4E0B;&#x6807;
                m=n-1-j
                #&#x5224;&#x65AD;&#x4E0B;&#x6807;&#x662F;&#x5426;&#x5BF9;&#x5E94;
                if m+a[i][j]-1==i:
                    maxlen=a[i][j]
                    maxend=i

    return s[maxend-maxlen+1:maxend+1]

print(longestPalindrome("abacd"))

我们从代码可以看出,时间复杂度为O(n2),空间复杂度也是O(n2)。

我们来看一下空间复杂度还能进行优化吗?

20211202完全对称日,我们一起来温习一下

我们来分析一下循环逻辑,i=0,然后遍历j=0,1,2,3。更新一列,然后i=1,再更新一列,更新的时候,我们只需要上一列的信息。所以,我们可以用一个一维数组来保存就好了。我们看一下代码实现。

def longestPalindrome(s):
    if s=="":
        return ""
    #&#x5B57;&#x7B26;&#x4E32;&#x53CD;&#x8F6C;
    t=s[::-1]
    n=len(s)
    a=[0 for _ in range(n)]
    maxlen=0
    maxend=0
    for i in range(n):
        for j in range(n-1,-1,-1):
            if(s[i]==t[j]):
                if i == 0 or j == 0:
                    a[j]=1
                else:
                    a[j]=a[j-1]+1
            else:
                a[j]=0

            if a[j] > maxlen:
                #&#x7FFB;&#x8F6C;&#x524D;&#x5BF9;&#x5E94;&#x7684;&#x4E0B;&#x6807;
                m=n-1-j
                #&#x5224;&#x65AD;&#x4E0B;&#x6807;&#x662F;&#x5426;&#x5BF9;&#x5E94;
                if m+a[j]-1==i:
                    maxlen=a[j]
                    maxend=i

    return s[maxend-maxlen+1:maxend+1]

print(longestPalindrome("abacd"))

所以,我们可以把空间复杂度降低为O(n)。

到此为止,我们就把最长回文子串这个问题说完了。

最后

最长回文子串作为校招和社招中常见的算法题,是需要我们掌握的。对于有”重叠子问题”特征的问题,我们首先要考虑采用动态规划的方法来解决。

今天,我们就聊到这里。更多有趣知识,请关注。

你知道的越多,你的思维也就越开阔,我们下期再见。

Original: https://www.cnblogs.com/cxyxz/p/15632590.html
Author: 算法推荐管
Title: 20211202完全对称日,我们一起来温习一下

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/713335/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • es通过时间聚合查询一周中每天的数据平均值

    场景回顾:设备上传的数据保存在es中,大屏模块要统计本周的数据折线图(一个设备三分总上传一次,所以拟定每天聚合求个平均值) kibana查询请求 GET xxxx_2022-10/…

    技术杂谈 2023年7月24日
    073
  • 使用iconv进行编码gb2312转utf8转码失败的坑

    iconv 编码gb2312转utf8 转码失败的坑 使用背景 项目中使用thrift进行C#程序调用c++接口,其中的协议是通过json进行传输的,由于默认thrift使用utf…

    技术杂谈 2023年7月23日
    079
  • JVM诊断命令jcmd介绍

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介 从JDK7开始,jdk提供了一个方便扩展的诊断命令jcmd,用来取代之前比较分散的jdk基础命…

    技术杂谈 2023年7月24日
    073
  • Mysql底层索引使用B+树(数据结构学习感悟)

    Mysql底层索引使用B+树(数据结构学习感悟) 注:本文仅代表个人观点,没有任何依据,如有错误,敬请斧正 考研学习数据结构,有了比之前更深的认识,或者说数据结构运用无处不在,如H…

    技术杂谈 2023年7月11日
    060
  • Game Engine Architecture 2

    【 Game Engine Architecture 2】 1、endian swap 函数 floating-point endian-swapping:将浮点指针reinter…

    技术杂谈 2023年5月31日
    078
  • 平台接口建设规范

    建设目标 平台接口建设规范旨在为接口开发、测试、使用划定一个框架边界,明确技术目标与要求,并要求提供完备的接口文档说明,为自有平台与第三方平台提供数据及服务支持。 建设标准 接口规…

    技术杂谈 2023年7月25日
    094
  • 关于PostMan的一个坑

    疯狂翻车记录: 当我请求 http://localhost:8080/rs/publish/action时, 如下所示: 发现后端收到的body为空 为什么我说是postman的问…

    技术杂谈 2023年5月31日
    0116
  • flink-kafka-connector 的实现

    简单介绍 flink-kafka-connector用来连接kafka,用于消费kafka的数据, 并传入给下游的算子。 使用方式 首先来看下flink-kafka-connect…

    技术杂谈 2023年6月21日
    0115
  • MySql数据库备份与还原

    备份(mysqldump) 实现功能: 1、备份指定的数据库 2、删除指定天数前的备份文件,默认设定了1天 脚本示例(mysql_bak.sh) &#x6570;&…

    技术杂谈 2023年6月21日
    080
  • 自定义TREEVIEWUL无限极嵌套

    背景:做一个多级图片分类管理,当然要用到TreeView,在asp.net中已经提供了此服务器控件,参照效果,自定义一个简单可控性高的就当做练手吧! 效果:如图,小图标 折叠 展开…

    技术杂谈 2023年7月23日
    093
  • 5分钟搞定MySQL到PolarDB-X数据迁移和同步-CloudCanal实战

    CloudCanal 近期支持了 PolarDB-X 对端, 目前开放的链路为 MySQL 到 PolarDB-X 。 本链路特点包括 完整支持结构迁移、全量迁移、增量同步、数据校…

    技术杂谈 2023年7月24日
    064
  • Java — 反射

    程序在运行中也可以获取类的变量和方法信息,并通过获取到的信息来创建对象。程序不必再编译期就完成确定,在运行期仍然可以扩展。 示例:学生类 public class Student …

    技术杂谈 2023年7月11日
    073
  • 自己动手实现一个简单的 IOC容器

    控制反转,即Inversion of Control(IoC),是面向对象中的一种设计原则,可以用有效降低架构代码的耦合度,从对象调用者角度又叫做依赖注入,即Dependency …

    技术杂谈 2023年7月25日
    0224
  • 技术管理进阶——一线Leader怎么做?经理的速成宝典

    原创不易,求分享、求一键三连本期培训材料关注公众号后回复: 经理培训,获得 前段时间有个同学问我有没有一线Leader的 速成培训课程,很好的问题,首先我们需要定义一下什么是小Le…

    技术杂谈 2023年6月1日
    0110
  • 关于连接服务器redis的教程

    第一步:下载RedisDesktopManager 这个百度一搜就有了,但是现在的版本ssh用不了建议找可以用的版本,这个百度,懂得都懂。 第二步:服务器宝塔redis设置 在配置…

    技术杂谈 2023年7月25日
    078
  • Android:hook很“危险”,使用需谨慎。

    前言 上篇文章《Android安卓进阶技术分享之AGP工作原理》和大家分析了 AGP(Android Gradle Plugin) 做了哪些事,了解到 AGP 就是为打包这个过程服…

    技术杂谈 2023年7月10日
    0103
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球