思维导图轻松掌握:LeetCode 300 题之(5)最长回文子串
2024-01-17 10:19:43
最长回文子串:三种算法详解
在字符串处理中,寻找最长的回文子串是一个常见的挑战。回文子串是指正着读和倒着读都一样的字符串,例如 "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)
优点:
- 简单易懂
- 对大多数情况适用
缺点:
- 时间复杂度较高
结论
本文详细介绍了查找最长回文子串的三种算法,并通过思维导图、代码示例和详细解释,帮助读者全面理解这一问题。动态规划算法简单易懂,适用于所有情况,但时间复杂度较高。马拉车算法速度快,适用于大多数情况,但预处理字符串的过程可能会影响性能。中心扩展算法简单高效,对大多数情况适用,但时间复杂度也较高。具体选择哪种算法取决于实际应用场景和性能要求。
常见问题解答
-
什么是回文子串?
回文子串是指正着读和倒着读都一样的字符串,例如 "racecar" 或 "level"。 -
查找最长回文子串的算法有哪些?
本文介绍了动态规划、马拉车和中心扩展算法。 -
哪种算法最有效率?
马拉车算法速度最快,时间复杂度为 O(n)。 -
哪种算法最简单?
中心扩展算法简单易懂,实现难度较低。 -
如何选择合适的算法?
选择算法时需要考虑实际应用场景和性能要求。如果需要高速处理,则马拉车算法是一个不错的选择。如果需要简单易懂的算法,则中心扩展算法更合适。