返回

思维导图轻松掌握:LeetCode 300 题之(5)最长回文子串

前端

最长回文子串:三种算法详解

在字符串处理中,寻找最长的回文子串是一个常见的挑战。回文子串是指正着读和倒着读都一样的字符串,例如 "racecar" 或 "level"。本文将深入探讨三种查找最长回文子串的算法,并通过思维导图、代码示例和详细解释,帮助读者全面理解这一问题。

思维导图:算法概览

最长回文子串算法思维导图

方案 1:动态规划

思路:
动态规划算法以递推的方式解决问题。它创建一个二维数组 dp,其中 dp[i][j] 表示子串 s[i:j+1] 是否是回文子串。通过检查较短子串的回文性,我们可以推导出较长子串的回文性。

代码:

def longest_palindrome_dp(s):
    n = len(s)
    dp = [[False] * n for _ in range(n)]

    # 初始化
    for i in range(n):
        dp[i][i] = True

    # 从短子串开始,依次考虑更长的子串
    for l in range(2, n+1):
        for i in range(n-l+1):
            j = i + l - 1
            if l == 2:
                dp[i][j] = (s[i] == s[j])
            else:
                dp[i][j] = (s[i] == s[j] and dp[i+1][j-1])

    # 找到最长回文子串的长度和起始位置
    max_len = 0
    start = 0
    for i in range(n):
        for j in range(n):
            if dp[i][j] and j - i + 1 > max_len:
                max_len = j - i + 1
                start = i

    return s[start:start+max_len]

时间复杂度: O(n^2)
空间复杂度: O(n^2)

优点:

  • 容易理解和实现
  • 对所有情况都适用

缺点:

  • 时间复杂度较高

方案 2:马拉车算法

思路:
马拉车算法是一种线性的算法,它将字符串预处理为一个新的字符串,以便于快速检查回文子串。该算法从字符串的中心向两边扩展,寻找最长的回文子串。

代码:

def longest_palindrome_manacher(s):
    # 预处理字符串
    t = '#' + '#'.join(s) + '#'

    # 中心扩展算法
    n = len(t)
    c = 0
    r = 0
    max_len = 0
    start = 0
    p = [0] * n

    for i in range(1, n-1):
        # 计算以 i 为中心的回文子串的半径
        i_mirror = 2 * c - i
        if i < r:
            p[i] = min(r - i, p[i_mirror])

        # 扩展回文子串
        while i + p[i] + 1 < n and i - p[i] - 1 >= 0 and t[i + p[i] + 1] == t[i - p[i] - 1]:
            p[i] += 1

        # 更新最长回文子串
        if p[i] > max_len:
            max_len = p[i]
            start = (i - max_len) // 2

        # 更新中心和右边界
        if i + p[i] > r:
            c = i
            r = i + p[i]

    return s[start:start+max_len]

时间复杂度: O(n)
空间复杂度: O(n)

优点:

  • 速度快
  • 对大多数情况适用

缺点:

  • 预处理字符串的过程可能会影响性能

方案 3:中心扩展算法

思路:
中心扩展算法是一种简单而有效的算法,它从字符串的中心向两边扩展,寻找最长的回文子串。该算法有两种扩展方式:奇数长度和偶数长度。

代码:

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

    longest = ""
    for i in range(len(s)):
        # 考虑奇数长度的回文子串
        palindrome1 = expand_around_center(i, i)
        if len(palindrome1) > len(longest):
            longest = palindrome1

        # 考虑偶数长度的回文子串
        palindrome2 = expand_around_center(i, i+1)
        if len(palindrome2) > len(longest):
            longest = palindrome2

    return longest

时间复杂度: O(n^2)
空间复杂度: O(1)

优点:

  • 简单易懂
  • 对大多数情况适用

缺点:

  • 时间复杂度较高

结论

本文详细介绍了查找最长回文子串的三种算法,并通过思维导图、代码示例和详细解释,帮助读者全面理解这一问题。动态规划算法简单易懂,适用于所有情况,但时间复杂度较高。马拉车算法速度快,适用于大多数情况,但预处理字符串的过程可能会影响性能。中心扩展算法简单高效,对大多数情况适用,但时间复杂度也较高。具体选择哪种算法取决于实际应用场景和性能要求。

常见问题解答

  1. 什么是回文子串?
    回文子串是指正着读和倒着读都一样的字符串,例如 "racecar" 或 "level"。

  2. 查找最长回文子串的算法有哪些?
    本文介绍了动态规划、马拉车和中心扩展算法。

  3. 哪种算法最有效率?
    马拉车算法速度最快,时间复杂度为 O(n)。

  4. 哪种算法最简单?
    中心扩展算法简单易懂,实现难度较低。

  5. 如何选择合适的算法?
    选择算法时需要考虑实际应用场景和性能要求。如果需要高速处理,则马拉车算法是一个不错的选择。如果需要简单易懂的算法,则中心扩展算法更合适。