Leetcode 最长回文子串

在这里插入图片描述
该算法的核心思想是使用中心扩展法(Expand Around Center),它通过从字符串的每个字符(或每对相邻字符)作为回文中心开始,向两边扩展来寻找回文子串。具体步骤如下:

1. 整体思路

  • 回文串有两种类型:

    • 奇数长度的回文串:例如 "aba",它的中心是单个字符。
    • 偶数长度的回文串:例如 "abba",它的中心是两个相邻字符。
  • 对于每个字符(或每对字符),我们尝试将它们作为回文的中心,向两侧扩展,直到不再满足回文条件。我们计算出当前回文的长度,然后与已知最长的回文长度进行比较,更新最长回文子串的起始和结束位置。

2. 详细步骤

  • 遍历整个字符串,假设每个字符或字符对是回文的中心。

  • 对于每个字符 i

    • 调用 expandAroundCenter(s, i, i) 来寻找以该字符为中心的奇数长度回文。
    • 调用 expandAroundCenter(s, i, i+1) 来寻找以该字符和下一个字符之间的缝隙为中心的偶数长度回文。
  • 比较两种情况下得到的回文长度,取较大的那个作为当前字符位置的最大回文长度。如果这个长度比已知的最大回文子串长度大,则更新最大回文子串的起始和结束位置。

3. 中心扩展法expandAroundCenter):

  • 该函数从传入的中心(可能是一个字符,也可能是两个字符)向外扩展,同时检查两边的字符是否相同。如果相同,则继续扩展;如果不同,则停止扩展。
  • 返回扩展后的回文长度。

4. 代码运行流程

  • 对于字符串中的每个字符位置,先以它为中心寻找奇数长度的回文,再以它和下一个字符为中心寻找偶数长度的回文。
  • 通过比较两者的长度,更新最长的回文子串。
  • 最终,返回找到的最长回文子串。

5. 时间复杂度

该算法的时间复杂度为 O(n^2),其中 n 是字符串的长度。虽然嵌套的循环看似复杂,但实际上每次扩展操作的时间都是线性的。因为每个字符最多被处理两次(一次作为奇数中心,一次作为偶数中心),所以整体的时间复杂度为 O(n^2)。

总结:

  • 中心扩展法是解决回文子串问题的一种高效方法,它的核心思想是从每个字符或字符对作为中心,向外扩展寻找最长回文。
  • 该方法的时间复杂度为 O(n^2),对于大多数实际问题来说是可接受的。
class Solution {
    public String longestPalindrome(String s) {

        int start = 0, end = 0;//用于记录最长回文子串的起始和终止下标
        for(int i = 0; i < s.length(); ++i) {
            int oddPalindromelen = expandAroundCenter(s, i, i);
            //这里传入的i+1是作为expandAroundCenter的参数,s字符串并不会访问到,不用担心越界。
            int evenPalindromelen = expandAroundCenter(s, i, i + 1);
            int maxPalindromeLen = Math.max(evenPalindromelen, oddPalindromelen);
            //更新最长回文子串的起始和终止下标
            if(maxPalindromeLen >= end - start + 1) { //新回文长度大于或等于当前回文长度时更新最长回文子串的边界
                start = i - (maxPalindromeLen - 1) / 2;
                end = i + maxPalindromeLen / 2;
            }
        }
        return s.substring(start, end + 1);
        
    }
    private int expandAroundCenter(String s, int left, int right) {
        while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
            left--;
            right++;
        }
        return right - left - 1; // 返回的是 right - left - 1,而不是 right - left + 1,
        // 原因是当 while 循环结束时,left 和 right 的值已经超出了有效回文串的边界。
    }
}
上一篇:每日回顾:简单用C写 归并排序


下一篇:物联网海量数据下的时序数据库选型:InfluxDB、TDEngine、MongoDB与HBase对比与建议