【字符串】-Lc5-最长回文子串(中心扩展法)

写在前面

最近想复习一下数据结构与算法相关的内容,找一些题来做一做。如有更好思路,欢迎指正。


目录


一、场景描述

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

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

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

示例 2:
输入:s = "cbbd"
输出:"bb"

二、具体步骤

1.环境说明

名称 说明
IntelliJ IDEA 2023.2

2.代码

以下为Java版本实现:

java 复制代码
public class Lc5_longestPalindrome {

    public static void main(String[] args) {
        // String s = "babad";
        String s = "cbbd";
        System.out.println(longestPalindrome(s));
    }

    /**
     * 思想:
     * 返回值是String
     *
     * 整体思路是从给的字符串中找到 2 个位置 start、end,然后从s.subString(start, end + 1)截取获得
     * 迭代的条件是,每次的返回回文子串的长度,如果比当前大,start和end就向2遍扩展
     *
     * 剩下的问题就是如何得到回文字串?
     * 思路是由中间向两边扩展(中心扩展法)
     *
     * 说明:
     * 回文中心,有 2 种方式
     *
     * 奇数长度回文:回文中心是1个字符,初始化 l = r =i,  得到的回文长度是奇数,1/3/5
     * 偶数长度回文:回文中心是2个字符,初始话 l=i, r=i+1,得到的回文长度是偶数,0/2/4
     *
     * for循环,i取值到 i < length - 1 即可 (最后一个数就不需要循环了)
     * 2种方式,由回文中心向两边扩展(lr双指针)
     *
     * 由中心向两边扩展,返回的是回文字串的长度
     * 计算2种方式的最大值与原有长度比较,如果大,则覆盖start和end
     */
    private static String longestPalindrome(String s) {
        int start = 0, end = 0;
        // 寻找回文中心
        for (int i = 0; i < s.length() - 1; i++) {
            // 回文中心是1个字符
            int oddLen = expandAroundCenter(s, i, i);
            // 回文中心是2个字符
            int evenLen = expandAroundCenter(s, i, i + 1);
            int len = Math.max(oddLen, evenLen);
            // 计算新的长度是否大于已存在的回文长度
            if (len >= end - start + 1) {
                /**
                 * 注意:回文中心是2个字符,回文长度是偶数时,计算start时,需要先把 len - 1,
                 *
                 * 示例:
                 * 索引        01 2345 6
                 * 字符串      ab dccd e
                 *
                 * 当 i = 3 时,回文中心是 cc,找到的回文字符串是 dccd
                 * start = 3 - (4 - 1) / 2 = 2
                 *       ≠ 3 - 4/2 = 1
                 */
                start = i - (len - 1) / 2;
                end = i + len / 2;
            }
        }

        return s.substring(start, end + 1);
    }

    /**
     * 中心扩展法
     * 以传入的参数为中心,向两边扩展,返回回文串的长度
     *
     * 数组求长度
     *  -101234
     *    babad
     * aba = (2 - 1) + 1 = 3
     *
     * @param s
     * @param left
     * @param right
     * @return
     */
    private static int expandAroundCenter(String s, int left, int right) {
        int l = left, r = right;
        for (; l >= 0 && r < s.length(); l--, r++) {
            if (s.charAt(l) != s.charAt(r)) {
                break;
            }
        }
        // 循环跳出时的l和r是不满足条件的(字符不相等 或者 超界),所以在计算时,有效的回文字符长度索引是 l + 1, r -1,
        // 数组通过索引求长度,需要再 +1
        // (r - 1) - (l + 1) + 1 = r - l - 1
        return r - l - 1;
    }


}

写在后面

如果本文内容对您有价值或者有启发的话,欢迎点赞、关注、评论和转发。您的反馈和陪伴将促进我们共同进步和成长。

相关推荐
陈老师还在写代码4 分钟前
安卓开发用Java、Flutter、Kotlin的区别
android·java·flutter
gentle_ice5 分钟前
搜索二维矩阵——巧用右上角起点搜索法,高效解决二维矩阵查找问题
数据结构·算法·leetcode·矩阵
鲤籽鲲13 分钟前
C# ManualResetEvent 类 使用详解
java·开发语言·c#·多线程
硬件人某某某38 分钟前
微信小程序~电器维修系统小程序
java·ajax·微信小程序·小程序
猿java40 分钟前
MySQL 如何实现主从复制?
java·后端·mysql
martian6651 小时前
【Java基础篇】——第4篇:Java常用类库与工具类
java·开发语言
violin-wang1 小时前
Intellij IDEA调整栈内存空间大小详细教程,添加参数-Xss....
java·ide·intellij-idea·xss·栈内存·栈空间
在下陈平安1 小时前
java-LinkedList源码详解
java·开发语言
黑客老李1 小时前
一次使用十六进制溢出绕过 WAF实现XSS的经历
java·运维·服务器·前端·sql·学习·xss
_不会dp不改名_1 小时前
leetcode_80删除有序数组中的重复项 II
数据结构·算法·leetcode