【每日一题】最长回文子串
给你一个字符串 s
,找到 s
中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <= 1000
s
仅由数字和英文字母组成
这题常规思路是用动规,如果一个回文串前后相邻的两字符相同,那么就可以扩张成一个新回文串。边界条件就是子串的长度为1或2,长为1的子串自然是回文串,长为2若两个字符相同那么也是回文串。换个角度我们也可以从边界条件外推,也就是中心扩展法。
class Solution:
def longestPalindrome(self, s: str) -> str:
# dp(i,j)表示s[i..j]是否是回文喘
# dp[i,i] = 1
# dp(i,i+1) = 1 when s[i]==s[i+1]
# dp(i,j) = 1 when dp(i+1,j-1)==1 and s[i]==s[j]
# 从边界条件向外扩展
def expand(s, l, r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1
r += 1
return l+1, r-1
l, r = 0, 0
for i in range(len(s)):
l1, r1 = expand(s, i, i) # 边界条件 长度为1的子串
l2, r2 = expand(s, i, i+1) # 边界条件 长度为2的子串
if (r1-l1) > (r-l):
l, r = (l1, r1)
if (r2-l2) > (r-l):
l, r = (l2, r2)
return s[l: r+1]
面试考到这道题发现忘了。。更一个动规解法:
class Solution:
def longestPalindrome(self, s: str) -> str:
# dp[i][j]:下标从i到j的子串是否回文
# dp[i][i] = 1
# dp[i][i+1] = 1 if s[i] == s[i+1]
# dp[i][j] = 1 if dp[i+1][j-1]=1 & s[i]==s[j]
n = len(s)
if n < 2:
return s
dp = [[False] * n for _ in range(n)]
for i in range(n):
dp[i][i] = True
start = 0
max_len = 1
# 长度为2的回文子串
for i in range(n-1):
if s[i] == s[i+1]:
dp[i][i+1] = True
start = i
max_len = 2
# 检查长度大于2的子串
for length in range(3, n+1):
for i in range(n-length+1):
j = i + length - 1
if dp[i+1][j-1] and s[i] == s[j]:
dp[i][j] = True
if length > max_len:
max_len = length
start = i
return s[start:start+max_len]
时间复杂度是O(n^2),空间复杂度也是O(n^2)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧