【LeetCode热题100】打开第5天:最长回文子串

news/2024/11/20 13:32:36/

文章目录

  • 最长回文子串
    • ⛅前言
    • 🔒题目
    • 🔑题解

最长回文子串

⛅前言

大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!

精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。

博客主页💖:知识汲取者的博客

LeetCode热题100专栏🚀:LeetCode热题100

Gitee地址📁:知识汲取者 (aghp) - Gitee.com

Github地址📁:Chinafrfq · GitHub

题目来源📢:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激

🔒题目

原题链接:5. 最长回文子串 - 力扣(LeetCode)

在这里插入图片描述

🔑题解

  • 解法一:暴力枚举

    这个方法简单、粗暴,但是想通过显然是想多了🤣LeetCode还没有这么水

    解题思路很简单,这里也就不展开来讲了,主要是对字符串所有可能出现的子串进行一个判断,然后得到最大子串。

    我这段代码有一个小注意点,那就是二层遍历要取等,因为substring方法是包前不包后的,如果不取等,当s的长度为2时,比如“aa”,最终的结果仍会是a,而不是aa,因为不取等压根就无法截取到第二个a

    /*** @author ghp* @title 最长回文子串*/
    class Solution {public String longestPalindrome(String s) {if (s.length() == 1){return s;}int max = Integer.MIN_VALUE; // 记录当前最大回文子串的长度String result = null; // 记录最大回文子串// 遍历所有子串for (int i = 0; i < s.length(); i++) {for (int j = i + 1; j <= s.length(); j++) {String target = s.substring(i, j);// 判断是否是当前最大回文串if (isPalindrome(target) && target.length() > max) {max = target.length();result = target;}}}return result;}/*** 判断是否是回文字符串* @param target* @return true-是 false-否*/private boolean isPalindrome(String target) {StringBuilder sb = new StringBuilder(target);String reverse = sb.reverse().toString();return reverse.equals(target);}
    }
    

    复杂度分析:

    • 时间复杂度: O ( n 3 ) O(n^3) O(n3)
    • 空间复杂度: O ( 1 ) O(1) O(1)

    其中 n n n 为字符串中字符的个数。之所以是 n 3 n^3 n3是因为reverse()的时间复杂度度是 O ( n ) O(n) O(n)

    在这里插入图片描述

  • 解法二:中心扩散算法(又学到一个新思想 o( ̄▽ ̄)ブ )

    主要思想:通过选取中心点,然后以中心点为根据地往两边扩散。

    实现步骤:

    • Step1:选取中心点。由于回文串存在单数与双数,所以中心点选取存在两种方式,如果是奇数中心点直接为单个字符,如果是偶数中心点直接为两个字符之间的间隔

      在这里插入图片描述

    • Step2:以中心点为根据地,往两边扩散。

    • Step3:遍历字符串所有的中心点。

    需要注意的点是计算回文串的长度,这里可能一下看不出规律,需要手动推导一下

    在这里插入图片描述

    /*** @author ghp* @title 最长回文子串*/
    class Solution {public String longestPalindrome(String s) {if (s.length() == 1) {// 这里可以省略(后面判断兼顾了长度为1的情况),但是还是建议能早返回的尽量找点返回return s;}int start = 0; // 最长回文子串的起始索引int end = 0; // 最长回文子串的结束索引int len = 0;for (int i = 0; i < s.length(); i++) {// 回文子串长度为奇数时int len1 = centerSpread(s, i, i);// 回文子串长度为偶数时int len2 = centerSpread(s, i, i + 1);// 获取当前最大回文子串的长度len = len1 >= len2 ? len1 : len2;// 计算最大回文传的起点和终点(只有当最大回文串的长度发生变化时才需要重新计算)if (len > end - start) {// 这里的计算公式,可以手动推导一下,有规律start = i - (len - 1) / 2;end = i + len / 2;}}return s.substring(start, end + 1);}/*** 中心扩散** @param s* @param l 中心点左边界* @param r 中心点右边界* @return 中心扩散后能够形成的 最长回文子串的长度*/private int centerSpread(String s, int l, int r) {while (l >= 0 && r <= s.length() && s.charAt(l) == s.charAt(r)) {l--;r++;}return r - l - 1;}
    }
    

    复杂度分析:

    • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
    • 空间复杂度: O ( 1 ) O(1) O(1)

    其中 n n n 为数组中元素的个数

  • 解法三:动态规划

    主要思路:我们可以直到回文串的规律,如果一个子串是回文串,那么往他前后在添加一个相同字符,它仍然是回文串。也就是说我们可以得到一个状态方程 P ( i , j ) = P ( i + 1 , j − 1 ) ∧ ( S i = = S j ) P(i,j)=P(i+1,j−1)∧(Si==Sj) P(i,j)=P(i+1,j1)(Si==Sj),因此我们可以从长度较短的回文串往长度较长的回文转进行一个状态转移,从而不断转换,最终得到最长回文子串

    public class Solution {public String longestPalindrome(String s) {int len = s.length();if (len < 2) {return s;}int maxLen = 1;int begin = 0;// dp[i][j] 表示 s[i..j] 是否是回文串boolean[][] dp = new boolean[len][len];// 初始化:所有长度为 1 的子串都是回文串for (int i = 0; i < len; i++) {dp[i][i] = true;}char[] charArray = s.toCharArray();// 递推开始// 先枚举子串长度for (int L = 2; L <= len; L++) {// 枚举左边界,左边界的上限设置可以宽松一些for (int i = 0; i < len; i++) {// 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得int j = L + i - 1;// 如果右边界越界,就可以退出当前循环if (j >= len) {break;}if (charArray[i] != charArray[j]) {dp[i][j] = false;} else {if (j - i < 3) {dp[i][j] = true;} else {dp[i][j] = dp[i + 1][j - 1];}}// 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置if (dp[i][j] && j - i + 1 > maxLen) {maxLen = j - i + 1;begin = i;}}}return s.substring(begin, begin + maxLen);}
    }作者:LeetCode-Solution
    链接:https://leetcode.cn/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode-solution/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

    复杂度分析:

    • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
    • 空间复杂度: O ( n 2 ) O(n^2) O(n2)

    其中 n n n 为数组中元素的个数

  • 解法四:Manacher 算法

    这个算法可以说是回文串相关题目的最优算法了,时间复杂度直接降到了 O ( n ) O(n) O(n),但是实现起来是最复杂的,这里不做解释说明了,想了解的可以参考LeetCode官网


http://www.ppmy.cn/news/98463.html

相关文章

FAST-LIO论文阅读

论文&#xff1a;FAST-LIO: A Fast, Robust LiDAR-inertial Odometry Package by Tightly-Coupled Iterated Kalman Filter 源码链接 各位大佬对论文的解析&#xff1a; FAST-LIO论文解读与详细公式推导 FAST-LIO是港大MaRS实验室在2021年提出的一个紧耦合迭代扩展卡尔曼滤波…

大数据技术之SparkCore

第1章 RDD概述 1.1 什么是RDD RDD&#xff08;Resilient Distributed Dataset&#xff09;叫做弹性分布式数据集&#xff0c;是Spark中最基本的数据抽象。 代码中是一个抽象类&#xff0c;它代表一个弹性的、不可变、可分区、里面的元素可并行计算的集合。 RDD代表的是弹性、…

django组件552

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

携程算法岗笔试【20230525】

前两天写了携程的一道笔试题&#xff0c;感觉题目质量挺不错&#xff0c;这里记录一下。 1. 题目 题目大意如下&#xff1a; 现有n套试卷&#xff0c;每套试卷包含的题目数是i。游游每天的早上和下午都可以选择做一套试卷&#xff0c;当然也可以选择摸鱼&#xff08;不做题&a…

6.6.4 PCS创建Oracle 资源及资源组

在RHCS体系中&#xff0c;Oracle的启动是按以下顺序进行的&#xff1a; VIP。监听器。逻辑卷&#xff08;ISCSI共享出来的&#xff09;。文件系统&#xff08;在逻辑卷上创建&#xff09;。数据库实例。 上边这些资源&#xff0c;在PCS里创建好以后&#xff0c;将其组合成一个…

注册的业务、登录业务、个人中心、nginx配置【VUE项目】

登录与注册静态组件-&#xff08;处理共用图片资源问题&#xff09; 登录与注册功能&#xff08;git&#xff09;&#xff1a;必须要会的技能 登录与注册的静态组件assets文件夹----全部组件共用的静态资源在样式当中也可以使用符号【src别名】&#xff0c;切记在前面加上~ …

【Redis】共同关注列表与基于Feed流的关注消息滚动分页推送的实现

目录 一、共同关注 1、思路 2、实现步骤 二、Feed流 1、概念 2、需求 3、TimeLine的三种模式 1.拉 2.推 3.推拉结合 4、TimeLine三种模式的区别 三、关注推送 1、需求 2、实现思路 3、Redis数据结构的选择 4、滚动分页 5、代码实现 1.博主 2.粉丝 一、共同关…

零基础自学黑客【网络安全】啃完这些足够了

我刚学网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#xff1f;有哪些方向&#xff1f;怎么选&#xff1f; 怎么入门&#xff1f; 这个 Web 安全学习路线&#xff0c;整体大概半年左右&#xff0c;具体视每个人的情况而定。 &#xff08;上传一直很模糊&#xff0c…