最长回文子串

126 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

背景

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

示例 1:

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

输入:s = "cbbd" 输出:"bb"

提示:

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

感兴趣的小伙伴可以查看原题:leetcode.cn/problems/lo…

分析

由题意可知,我们首先要判断什么是回文;回文就是字符串翻转后和翻转前一模一样,比如"上海自来水来自海上",翻转后依然是"上海自来水来自海上";下面我们使用java代码作为示例来看看如何判断回文:

private boolean isPalindrome(String s){
    // 当前字符串是否和翻转后的字符串一样
    return s.equals(new StringBuilder(s).reverse().toString());
}

我们可以使用JDK中现有的reverse()方法来判断是否是回文;也可以自己实现回文的判断:

    private boolean isPalindrome(String s){
        // 取出字符串的长度
        int len = s.length();
        // 首尾压缩
        for(int i=0;i<len-i-1;i++){
            // 从前向后取字符
            char a = s.charAt(i);
            // 从后向前取字符
            char b = s.charAt(len-i-1);
            // 比较两个字符大小,一旦不相等,就说明不是回文
            if(a-b!=0){
                // 不是回文
                return false;
            }
        }
        // 全部比较完毕后,没有发现不相等的字符,说明是回文
        return true;
    }

另一个问题就是如何判断是否是最长的回文,我们需要创建两个索引值从字符串的首尾向中间压缩来判断中间的字符串是否是最长回文;

下面我们使用hello这个字符串来举例子,通过图示的方式来简要概述一下算法的过程:

image-20220823135253716.png

image-20220823135417241.png

image-20220823135448948.png

image-20220823135512504.png

image-20220823135531812.png

image-20220823135547348.png

image-20220823135602426.png

image-20220823135622519.png

image-20220823135642754.png

image-20220823135655404.png

java实现

// 判断是否是回文
private boolean isPalindrome(String s){
    return s.equals(new StringBuilder(s).reverse().toString());
}
​
public String longestPalindrome(String s) {
        // 如果字符串中只有一个字符,或者直接可以判断是回文,那么最长回文肯定是本身
        if(s.length()==1||isPalindrome(s)){
            // 直接返回当前字符串
            return s;
        }
        // 先默认一个字符作为结果
        String result=s.substring(0,1);
        // 目前的最长长度为1
        int sum = 1;
        // 获取字符串长度
        int len = s.length();
        // 使用双重循环从首尾开始压缩
        // 从前向后取字符
        for(int i=0;i<len;i++){
            // 取出前面的字符
            Character a = s.charAt(i);
            // 从后向前取字符
            for(int j=len-1;j>i;j--){
                // 取出后面的字符
                Character b = s.charAt(j);
                // 如果两个字符不一样,肯定不是回文,那么继续向前取字符,找下一个最长回文
                if(!a.equals(b)){
                    // 继续向前取字符
                    continue;
                }
                // 如果字符一样,那么我们把字符间的字符串截取出来
                String ss=s.substring(i,j+1);
                // 判断截取的字符串是否是回文,如果不是回文,那么继续向前取字符,找下一个最长回文
                if(!isPalindrome(ss)){
                    // 不是回文,继续向前取字符
                    continue;
                }
                // 如果是回文,那么还要判断当前回文的长度是否是最长的
                if(ss.length()<sum){
                    // 如果当前的回文长度不是最长的,继续向前取字符,找下一个最长回文
                    continue;
                }
                // 到这里,说明当前的回文是最长的了,那么把最长回文做一下记录,以便与下一个回文比较
                sum = ss.length();
                result = ss;
            }
        }
        // 全部循环完毕后,返回最长回文
        return result;
    }

小伙伴们也可以使用自己喜欢的编程语言来实现这个题目的题解哦,感谢您的阅读!