返回

LeetCode #5 求最长的镜像字符串详解:从中心扩散求最长回文子串

IOS

挑战和思路
LeetCode #5 求最长的镜像字符串,对于初学者来说,可能并不容易理解。我们需要找出给定字符串中最长的回文子串。回文子串是指正序读和倒序读都一样的子字符串。这道题的挑战在于,我们不能使用蛮力法来解决,因为这样会非常耗时。我们需要使用更有效的方法,比如中心扩散法和动态规划法。

算法实现:中心扩散法
中心扩散法是一种非常有效的方法,可以用来求解最长回文子串的问题。中心扩散法的基本思想是,从字符串的中心向两侧扩展,直到遇到不匹配的字符为止。然后,我们将中心移动到下一个字符,并重复这个过程。这样,我们就能够找到字符串中所有可能的回文子串,并从中选择最长的一个。

算法实现:动态规划
动态规划是一种自底向上的方法,可以用来求解最长回文子串的问题。动态规划的基本思想是,将问题分解成更小的子问题,然后逐步解决这些子问题,最终得到问题的解。在求解最长回文子串的问题时,我们可以将字符串分解成一个个子串,然后判断每个子串是否为回文子串。如果一个子串是回文子串,那么它的长度就是它的最长回文子串的长度。

参考代码:中心扩散法

def longestPalindrome(s):
  """
  中心扩散法
  """
  if not s:
    return ""

  n = len(s)
  start, end = 0, 0

  for i in range(n):
    l, r = i, i
    while l >= 0 and r < n and s[l] == s[r]:
      if r - l + 1 > end - start:
        start, end = l, r
      l -= 1
      r += 1

    l, r = i, i + 1
    while l >= 0 and r < n and s[l] == s[r]:
      if r - l + 1 > end - start:
        start, end = l, r
      l -= 1
      r += 1

  return s[start:end + 1]

参考代码:动态规划法

def longestPalindrome(s):
  """
  动态规划法
  """
  if not s:
    return ""

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

  start, end = 0, 0

  for i in range(n - 1, -1, -1):
    dp[i][i] = True
    for j in range(i + 1, n):
      if s[i] == s[j]:
        if j - i <= 2 or dp[i + 1][j - 1]:
          dp[i][j] = True
          if j - i + 1 > end - start:
            start, end = i, j

  return s[start:end + 1]

代码分析
在中心扩散法中,我们首先判断字符串是否为空,如果是空字符串,则直接返回空字符串。然后,我们使用一个for循环遍历字符串中的每个字符,并以每个字符为中心向两侧扩展。如果我们找到一个回文子串,并且它的长度大于我们之前找到的最长回文子串的长度,那么我们就更新start和end变量的值。

在动态规划法中,我们首先判断字符串是否为空,如果是空字符串,则直接返回空字符串。然后,我们使用一个二维数组dp来存储字符串中每个子串是否是回文子串。我们使用一个for循环遍历字符串中的每个字符,并以每个字符为中心向两侧扩展。如果我们找到一个回文子串,并且它的长度大于我们之前找到的最长回文子串的长度,那么我们就更新start和end变量的值。

复杂度分析
中心扩散法的复杂度为O(n^2),其中n是字符串的长度。动态规划法的复杂度为O(n^2),其中n是字符串的长度。

总结
中心扩散法和动态规划法都是求解最长回文子串问题的有效方法。中心扩散法比较简单,但时间复杂度较高。动态规划法比较复杂,但时间复杂度较低。在实际应用中,我们可以根据具体情况选择使用哪种方法。