【算法】最长回文子串

193 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情

题目

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

解题思路

关键词:回文字符串;镜像相等;

关键信息:奇数偶数字符串判断;

字符串遍历解法

最简单的方式对字符串做遍历查询:遍历每个字符所有可能性。

  1. 从字符串第一个字符开始遍历查询,以该字符为起点向进行字符串裁剪(substring)
  2. 检查裁剪后字符串是否符合回文条件
  3. 将符合条件字符串进行比较找到最长字符串保留。
  4. 遍历所有情况后输出保留的最长字符串。
	public boolean isPalindrome(String text){ // 检查是否是回文字符串
        int i = 0,j = text.length() - 1;
        while(j > i){
            if(text.charAt(i) != text.charAt(j))
                return false;
            i++;
            j--;
        }
        return true;
    }
    public String longestPalindrome(String s) {
        int length = s.length();
        String palindromeText = s.substring(0,1);
        for(int i = 0;i < length;i++){
            int right = length - 1;
            while(right > i){
                String temp = s.substring(i,right + 1);
                if(isPalindrome(temp) && temp.length() > palindromeText.length()){
                     palindromeText = temp;
                }
                right --;
            }
        }
        return palindromeText;
    }

PS:上述算法可解决问题但会超出时间限制(算法效率过低)

通过优化算法代码跳过忽略掉后续无用遍历情况(当后续遍历字符串长度小于已知回文字符串时直接跳过即可)。

 while(right > i && (right + 1 - i > palindromeText.length())) // 增加一个条件判断

中心点扩散解法

中心扩散解法以某个字符为中心向两边扩散,直到不为回文串或者到边界为止。遍历完整条字符串的扩散方法后比较得到最长的回文串即可。

  1. 遍历每个字符往左右做扩散查询是否为回文串
  2. 由于字符串可能是偶数也可能是奇数因此在做查询时需要设定以i,i以及i,i+1为初始值做两次扩散
  3. 例如像"abba"这种特殊字符必须依照上述方式才能检查出来
  4. 如上遍历所有可能存在回文串后比较得到最长回文串输出。
public String getPalindrome(String text,int left,int right){ // 检查是否是回文字符串
        while(left >= 0 && 
              right < text.length() && 
              text.charAt(left) != text.charAt(right)){
            right++;
            left--;
        }
        return text.substring(text,right+ 1,left);
}
public String longestPalindrome(String s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }
        int maxLen = 1;
        String res = s.substring(0, 1);
        for (int i = 0; i < len - 1; i++) {
            String oddStr = centerSpread(s, i, i); 
            String evenStr = centerSpread(s, i, i + 1); 
            String maxLenStr = oddStr.length() > evenStr.length() ? oddStr : evenStr;
            if (maxLenStr.length() > maxLen) {
                maxLen = maxLenStr.length();
                res = maxLenStr;
            }
        }
        return res;
}

参考