LeetCode热题100:5.最长回文子串

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

示例 1:

复制代码
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

复制代码
输入:s = "cbbd"
输出:"bb"

提示:

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

直接上代码,不懂请留言或私信我

java 复制代码
class Solution {

    public String longestPalindrome(String s) {
        //s的最小长度为1,如果只有长度1,直接返回自己
        if(s.length() == 1) {
            return s;
        }    
        //转换为字符数组进行操作
        char[] sArr = s.toCharArray();
        //转换为Manacer字符数组
        char[] manacerArr = getManacerArr(sArr);
        /**定义两个变量mostRight表示以某个位置为圆心的回文圆所能扩到的最右位置,maxCenter表示扩到mostRight
        的圆的直径,当前我们还没有遍历任何位置,这两个都设置为-1*/
        int mostRight = -1;
        int maxCenter = -1;
        //maxRadiusIndex表示最大半径出现的位置,现在可以设置为0
        int maxRadiusIndex = 0;
        /**maxRadiusArr表示以每个点为圆心的最大的回文直径,这里的半径和圆心所依赖的都是manacer这个数组的位置*/
        int[] maxRadiusArr = new int[manacerArr.length];
        /**curIndex表示当前到了哪个位置,当然我们从0开始遍历 */
        int curIndex = 0;
        /**最长的回文半径 */
        int maxRadius = 0;
        /**从0开始遍历一直到最后的位置*/
        while(curIndex < manacerArr.length) {
            //如果当前的位置在mostRight外就暴力扩(mostRight是以前面某个点为圆心的最右边的位置,在他前面有)
            if(curIndex > mostRight) {
                //目前暂定他的半径为0,如果能找到更长的就更新
                int r = 0;
                //持续比较他的左右对称位置看是否相等,这里需要判断是否越界
                //左边是
                while(curIndex - r - 1>= 0 && curIndex + r + 1 < manacerArr.length 
                && manacerArr[curIndex - r -1] == manacerArr[curIndex + r + 1]) {
                    r ++;
                }
                //以当前位置为圆心的回文半径最大到了r,记录到maxRadiusArr,并尝试更新max
                maxRadiusArr[curIndex] = r;
                //本来他就在mostRight的外面,必定能把mostRight右扩
                mostRight = curIndex + r;
                maxCenter = curIndex;
                if(r > maxRadius) {
                    maxRadius = r;
                    maxRadiusIndex = curIndex;
                }
            } else {
                /**如果i在mostRight的左边,就需要考虑i关于maxCenter的对称位置iMirror,分为三种情况
                1.如果iMirror为圆心的回文最左位置在maxCenter的回文左边界的右边,那i和它的半径一样
                2.如果iMirror为圆心的回文最左位置在maxCenter的回文左边界的左边,那i得回文右边界就是mostRight
                3.如果iMirror为圆心的回文最左位置和maxCenter的回文左边界的左边重合,则i的回文右边界至少在mostRight,可以尝试去扩展 */
                int iMirror = 2 * maxCenter - curIndex;
                int iMirrorLeftBound = iMirror - maxRadiusArr[iMirror];
                int maxCenterLeftBound = 2 * maxCenter - mostRight;
                if(iMirrorLeftBound > maxCenterLeftBound) {
                    maxRadiusArr[curIndex] = maxRadiusArr[iMirror];
                } else if(iMirrorLeftBound < maxCenterLeftBound) {
                    maxRadiusArr[curIndex] = mostRight - curIndex;
                } else {
                    /**最小半径是到mostRight,还可能更大,尝试扩展一下 */
                    int r = mostRight - curIndex;
                    while(curIndex - r - 1>= 0 && curIndex + r + 1 < manacerArr.length 
                        && manacerArr[curIndex - r - 1] == manacerArr[curIndex + r + 1]) {
                        r ++;
                    }
                    mostRight = curIndex + r;
                    maxCenter = curIndex;
                    if(r > maxRadius) {
                        maxRadius = r;
                        maxRadiusIndex = curIndex;
                    }
                    maxRadiusArr[curIndex] = r;
                }
            }
            curIndex ++;
        }
        /**最大回文子串在manacer中的是以maxCenter为圆心,maxRadius为直径的字符串
        回到原字符串中都除以2即可,但是记得subString的特性,后面不包含,所以要+1*/
        if(maxRadiusIndex % 2 == 1) {
            //在实轴上的时候
            return s.substring(maxRadiusIndex/2 - maxRadius/2, maxRadiusIndex/2 + maxRadius/2 + 1);
        } else {
            //在虚轴("#")上的时候
            return s.substring((maxRadiusIndex + 1)/2 - maxRadius/2, (maxRadiusIndex + 1)/2 + maxRadius/2 );
        }
        
    }

    public char[] getManacerArr(char[] arr) {
        //manacer就是把所有字符的间隔位置以及开头结尾加上#
        char[] manacerArr = new char[2*arr.length + 1];
        for(int i = 0; i < manacerArr.length; i++) {
            if(i % 2 == 0) {
                manacerArr[i] = '#';
            } else {
                manacerArr[i] = arr[i / 2];
            }
        }
        return manacerArr;
    }
    public void print(char[] arr) {
        for(int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]);
        }
    }
    public void print(int[] arr) {
        for(int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

运行结果:

相关推荐
NAGNIP7 小时前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
颜酱15 小时前
单调栈:从模板到实战
javascript·后端·算法
CoovallyAIHub18 小时前
仿生学突破:SILD模型如何让无人机在电力线迷宫中发现“隐形威胁”
深度学习·算法·计算机视觉
CoovallyAIHub19 小时前
从春晚机器人到零样本革命:YOLO26-Pose姿态估计实战指南
深度学习·算法·计算机视觉
CoovallyAIHub19 小时前
Le-DETR:省80%预训练数据,这个实时检测Transformer刷新SOTA|Georgia Tech & 北交大
深度学习·算法·计算机视觉
CoovallyAIHub19 小时前
强化学习凭什么比监督学习更聪明?RL的“聪明”并非来自算法,而是因为它学会了“挑食”
深度学习·算法·计算机视觉
CoovallyAIHub19 小时前
YOLO-IOD深度解析:打破实时增量目标检测的三重知识冲突
深度学习·算法·计算机视觉
NAGNIP1 天前
轻松搞懂全连接神经网络结构!
人工智能·算法·面试
NAGNIP1 天前
一文搞懂激活函数!
算法·面试
董董灿是个攻城狮1 天前
AI 视觉连载7:传统 CV 之高斯滤波实战
算法