LeetCode 经典题:“最长回文子串”

一、题目描述

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

示例

  • 示例 1
    • 输入s = "babad"
    • 输出"bab"
    • 解释"aba" 同样也是符合题意的答案。
  • 示例 2
    • 输入s = "cbbd"
    • 输出"bb"
  • 示例 3
    • 输入s = "a"
    • 输出"a"
  • 示例 4
    • 输入s = "ac"
    • 输出"a""c"

二、解题思路

1. 暴力解法

暴力解法是最直接的思路,通过枚举字符串的所有子串,然后判断每个子串是否为回文串,记录下最长的回文子串。

  • 枚举所有子串:使用两层循环,外层循环从字符串的第一个字符开始,到最后一个字符结束,确定子串的起始位置 i。内层循环从 i 开始,到字符串末尾结束,确定子串的结束位置 j,这样就得到了所有可能的子串 s[i:j + 1]
  • 判断子串是否为回文串:对于每个子串,通过比较子串的前半部分和后半部分是否相等来判断是否为回文串。可以使用双指针法,一个指针指向子串的开头,一个指针指向子串的末尾,向中间移动指针并比较对应字符是否相等。如果所有对应字符都相等,则该子串是回文串。

2. 中心扩展算法

回文串具有中心对称的特点,因此可以从字符串的每个字符或相邻两个字符为中心,向两边扩展,寻找最长的回文子串。

  • 单字符中心:对于字符串中的每个字符 s[i],可以将其作为回文串的中心,向两边扩展,即比较 s[i - 1]s[i + 1]s[i - 2]s[i + 2] 等等,直到两边字符不相等为止。
  • 双字符中心:对于相邻的两个字符 s[i]s[i + 1],如果它们相等,那么可以将这两个字符作为回文串的中心,同样向两边扩展,比较 s[i - 1]s[i + 2]s[i - 2]s[i + 3] 等等,直到两边字符不相等。
  • 记录最长回文子串:在扩展过程中,记录下每次找到的回文子串的长度和起始位置,最后根据记录的信息得到最长的回文子串。

三、代码实现

暴力解法(Python)

def longestPalindrome_brute(s):
    max_length = 0
    start = 0
    for i in range(len(s)):
        for j in range(i, len(s)):
            is_palindrome = True
            for k in range((j - i + 1) // 2):
                if s[i + k]!= s[j - k]:
                    is_palindrome = False
                    break
            if is_palindrome and (j - i + 1) > max_length:
                max_length = j - i + 1
                start = i
    return s[start:start + max_length]

中心扩展算法(Python)

def longestPalindrome(s):
    def expand_around_center(left, right):
        while left >= 0 and right < len(s) and s[left] == s[right]:
            left -= 1
            right += 1
        return right - left - 1

    start = 0
    max_length = 0
    for i in range(len(s)):
        length1 = expand_around_center(i, i)
        length2 = expand_around_center(i, i + 1)
        max_length = max(max_length, length1, length2)
        if max_length > (right - left + 1):
            if max_length == length1:
                start = i - (max_length - 1) // 2
            else:
                start = i - max_length // 2 + 1
    return s[start:start + max_length]

暴力解法(Java)

public class LongestPalindromicSubstringBrute {
    public String longestPalindrome(String s) {
        int maxLength = 0;
        int start = 0;
        for (int i = 0; i < s.length(); i++) {
            for (int j = i; j < s.length(); j++) {
                boolean isPalindrome = true;
                for (int k = 0; k < (j - i + 1) / 2; k++) {
                    if (s.charAt(i + k)!= s.charAt(j - k)) {
                        isPalindrome = false;
                        break;
                    }
                }
                if (isPalindrome && (j - i + 1) > maxLength) {
                    maxLength = j - i + 1;
                    start = i;
                }
            }
        }
        return s.substring(start, start + maxLength);
    }
}

中心扩展算法(Java)

public class LongestPalindromicSubstring {
    public String longestPalindrome(String s) {
        if (s == null || s.length() < 1) return "";
        int start = 0, end = 0;
        for (int i = 0; i < s.length(); i++) {
            int len1 = expandAroundCenter(s, i, i);
            int len2 = expandAroundCenter(s, i, i + 1);
            int len = Math.max(len1, len2);
            if (len > end - start + 1) {
                start = i - (len - 1) / 2;
                end = i + len / 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;
    }
}

四、复杂度分析

暴力解法

  • 时间复杂度O(n3)O(n^3)O(n3),其中 nnn 是字符串的长度。两层循环用于枚举所有子串,时间复杂度为 O(n2)O(n^2)O(n2),对于每个子串判断是否为回文串,时间复杂度为 O(n)O(n)O(n),所以总的时间复杂度为 O(n3)O(n^3)O(n3)
  • 空间复杂度O(1)O(1)O(1),除了存储结果的空间外,只使用了常数级别的额外空间。

中心扩展算法

  • 时间复杂度O(n2)O(n^2)O(n2),其中 nnn 是字符串的长度。对于字符串中的每个字符,最多需要向两边扩展 O(n)O(n)O(n) 次,所以总的时间复杂度为 O(n2)O(n^2)O(n2)
  • 空间复杂度O(1)O(1)O(1),只使用了常数级别的额外空间。

五、总结

“最长回文子串”问题通过暴力解法和中心扩展算法展示了不同的解题思路。暴力解法虽然直观但效率较低,中心扩展算法利用回文串的特性,显著提高了效率。在解决字符串相关问题时,深入理解字符串的特性并合理利用这些特性,能够设计出更高效的算法。希望通过对本题的学习,能增强你对字符串算法的理解和应用能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值