返回
用LeetCode-409:寻找最长回文串,提升你的算法技巧
前端
2024-01-04 00:30:05
回文探秘:LeetCode-409 算法详解
动态规划:通往回文之巅的阶梯
在算法竞技场中,LeetCode-409 挑战我们寻找给定字母序列中最长的回文串。回文串是一种正读反读都相同的字符串,如 "racecar" 或 "level"。
破解这一难题的利器便是动态规划算法。它将问题分解成一系列子问题,逐步求解,最终汇聚成全局最优解。
假设字符串为 s,长度为 n。我们创建一张二维表 dp,其中 dp[i][j] 表示子字符串 s[i:j+1] 是否为回文串。
子问题的定义:
- 当 i=j 时,dp[i][j] = True,因为任何单个字符都是回文串。
- 当 j-i=1 时,dp[i][j] = (s[i]==s[j]),即相邻字符相同。
- 当 j-i>1 时,dp[i][j] = (s[i]==s[j]) && dp[i+1][j-1],即相邻字符相同且子串 s[i+1:j] 为回文串。
递推公式:
dp[i][j] =
if i==j:
True
elif j-i==1:
s[i]==s[j]
else:
s[i]==s[j] && dp[i+1][j-1]
回溯路径:
求得 dp 表后,我们可以通过回溯,找到最长回文串的构成过程。从 dp[0][n-1] 开始,若 dp[i][j]=True,则将 s[i] 和 s[j] 加入结果串,并继续回溯 dp[i+1][j-1]。
代码实现:
def longest_palindrome(s):
n = len(s)
dp = [[False] * n for _ in range(n)]
max_len = 0
start = 0
# 填充dp表
for i in range(n):
dp[i][i] = True
for i in range(n-1):
dp[i][i+1] = s[i] == s[i+1]
# 递推求解
for k in range(2, n):
for i in range(n-k):
j = i + k
dp[i][j] = (s[i] == s[j]) and dp[i+1][j-1]
# 更新最长回文串
if dp[i][j] and k > max_len:
max_len = k
start = i
# 回溯构成过程
result = ""
i, j = start, start + max_len - 1
while i <= j:
result += s[i]
i += 1
j -= 1
return result
进阶拓展:算法之美
掌握了寻找最长回文串的算法后,不妨更进一步,探索它的变种问题:
- 最长回文子序列: 寻找字符串中最长的回文子序列,而不必相邻。
- 最长回文子串变位词: 在给定字符串中寻找任意变位词构成的最长回文子串。
算法世界无穷无尽,让我们乘风破浪,勇往直前,不断提升我们的算法思维和编程技巧!
常见问题解答
-
什么是回文串?
- 正读反读都相同的字符串,如 "racecar" 或 "level"。
-
动态规划算法如何破解回文串问题?
- 分解问题为子问题,逐步求解,最终汇聚成全局最优解。
-
为什么 dp[i][j] = dp[i+1][j-1]?
- 只有相邻字符相同时,且子串 s[i+1:j] 为回文串时,dp[i][j] 才为回文串。
-
如何回溯最长回文串的构成过程?
- 从 dp[0][n-1] 开始,若 dp[i][j]=True,则将 s[i] 和 s[j] 加入结果串,并继续回溯 dp[i+1][j-1]。
-
除了最长回文子串外,还有哪些回文串变种问题?
- 最长回文子序列、最长回文子串变位词等。