这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战
难度:中等
题目描述
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd" 输出:"bb"
示例 3:
输入:s = "a" 输出:"a"
示例 4:
输入:s = "ac" 输出:"a"
提示:
1 <= s.length <= 1000 s 仅由数字和英文字母(大写和/或小写)组成
解题思路
动态规划 做的题多了思路基本都一样:
-
dp[i][j]表示s[i:j]是否为回文串
-
如果s[i] == s[j],则dp[i][j] == dp[i+1][j-1]
-
每次更新完dp[i][j]之后,更新max_len和start边界
-
len(s) < 2时必为回文串
-
dp[i][i]=True
class Solution:
def longestPalindrome(self, s: str) -> str:
# 动态规划,dp[i][j]表示s[i:j]是否为回文子串
# 每次判断s[i][j]时更新maxlen=j-i+1和start=i
# 边界,当j-i+1<2时,肯定是回文串
n = len(s)
dp = [[False]*n for _ in range(n)]
start, lens = 0, 1
# 边界
if n < 2:
return s
# 初始化
for i in range(n):
dp[i][i] = True
# 枚举区间终点
for j in range(1, n):
# 枚举起点
for i in range(0, j):
if s[i] == s[j]:
if j - i < 3:
dp[i][j] = True
else:
dp[i][j] = dp[i+1][j-1]
if dp[i][j]:
l = j - i + 1
if l > lens:
lens = l
start = i
return s[start: start+lens]
这道题看似麻烦,但仔细考虑回文子串只有两种情况奇偶回文( aba abba )
那么我们只需要循环字符串的每一个index,当满足一下条件时,从中心向两边扩展:
- left >= 0
- right < len(s)
- s[left] == s[right]
对于第三个条件,存在奇数回文和偶数回文的判断:
- 奇数回文时,我们初始left == right
- 偶数回文时,我们初始化right == left + 1
class Solution:
def longestPalindrome(self, s):
nums = len(s)
# s为空或者s为自己本身的情况
if nums < 2:
return s
ret = ''
def finder(left, right):
nonlocal ret
while left >= 0 and right < nums and s[left] == s[right]:
left -= 1
right += 1
ret = s[left + 1:right] if right - left - 1 > len(ret) else ret
for i in range(nums ):
finder(i, i)
finder(i, i + 1)
return ret