返回
LeetCode 解题系列:最长回文子串全方位解法
前端
2023-11-30 17:25:37
作为一名刚刚起步的前端开发者,我怀着无比的渴望和敬畏之情踏上了 LeetCode 的解题之旅。在解决最长回文子串问题时,我如饥似渴地钻研了网络上的各种解法,并从中受益匪浅。为了回馈社区,我决定将自己的心得体会整理成文,与大家分享。
问题背景
给定一个字符串 s
,找出其中长度最长的回文子串。回文子串是指从左到右和从右到左读起来都相同的子串。例如,在字符串 "babad" 中,最长的回文子串是 "bab"。
解法一:动态规划
动态规划是一种自底向上的解决问题的技术。对于最长回文子串问题,我们可以构建一个二维表格 dp
,其中 dp[i][j]
表示字符串 s
从下标 i
到下标 j
的子串是否为回文串。
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 i in range(n - 1):
if s[i] == s[i + 1]:
dp[i][i + 1] = True
# 对于长度大于 2 的子串
for l in range(3, n + 1):
for i in range(n - l + 1):
j = i + l - 1
if s[i] == s[j] and dp[i + 1][j - 1]:
dp[i][j] = True
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]
解法二:马拉车算法
马拉车算法是一种寻找字符串中所有回文子串的算法。其核心思想是将每个字符作为回文子串的中心,然后向左右两侧扩展,直到找到回文子串的边界。
def longest_palindrome_manacher(s):
# 预处理字符串,在每个字符之间插入特殊字符 '#'
s = '#' + '#'.join(s) + '#'
# 构建马拉车数组
n = len(s)
p = [0] * n
center = right = 0
max_len = 0
for i in range(1, n - 1):
if i < right:
p[i] = min(right - i, p[2 * center - i])
while i - p[i] - 1 >= 0 and i + p[i] + 1 < n and s[i - p[i] - 1] == s[i + p[i] + 1]:
p[i] += 1
if i + p[i] > right:
center = i
right = i + p[i]
if p[i] > max_len:
max_len = p[i]
start = i - max_len
return s[start:start + max_len].replace('#', '')
解法三:中心扩展法
中心扩展法与马拉车算法类似,都是从每个字符作为回文子串的中心开始扩展。不同之处在于中心扩展法每次只扩展一个单位,直到找到回文子串的边界。
def longest_palindrome_center_expand(s):
max_len = 0
start = 0
for i in range(len(s)):
left, right = i, i
# 扩展奇数长度回文子串
while left >= 0 and right < len(s) and s[left] == s[right]:
if right - left + 1 > max_len:
max_len = right - left + 1
start = left
left -= 1
right += 1
# 扩展偶数长度回文子串
left, right = i, i + 1
while left >= 0 and right < len(s) and s[left] == s[right]:
if right - left + 1 > max_len:
max_len = right - left + 1
start = left
left -= 1
right += 1
return s[start:start + max_len]
性能比较
三种解法在不同情况下表现各有优劣。动态规划适用于任意字符串,时间复杂度为 O(n^2)。马拉车算法和中心扩展法更适合寻找最长回文子串,时间复杂度均为 O(n)。
总结
最长回文子串问题是 LeetCode 中经典且重要的题目。通过动态规划、马拉车算法和中心扩展法三种解法的讲解,我们深入剖析了回文子串的本质,掌握了不同的解题思路。希望这篇文章能给您带来启发,助您在 LeetCode 解题之旅中取得进步。