题目
- 给你一个字符串 s,找到 s 中最长的回文子串。
- 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例
- 示例一
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
- 示例二
输入:s = "cbbd"
输出:"bb"
提示
1 <= s.length <= 1000
- s 仅由数字和英文字母组成
思路及算法代码
思路
- 中心扩展法
- 首先定义了一个名为 expandAroundCenter 的方法,用于从给定的中心向两边扩展,检查回文串的长度。
- 在该方法中,通过一个循环来逐步扩展,直到左右两边的字符不再相等或者到达字符串的边界。
- 每次循环,left 向左移动一位,right 向右移动一位,同时检查左右字符是否相等,直到不满足回文串条件。
- 最后返回回文串的左右边界(即 left + 1 和 right - 1)。
- 遍历字符串:
- 接下来定义了 longestPalindrome 方法,用于遍历给定字符串中的每个字符。
- 对于每个字符,分别以该字符为中心和以该字符与下一个字符的间隙为中心,调用 expandAroundCenter 方法。
- 获取两次扩展中的回文串的边界。
- 更新最长回文子串:
- 在每次扩展中,通过比较当前找到的回文串与已知最长回文串的长度,来更新最长回文串的起始和结束位置。
- 如果当前找到的回文串更长,则更新 start 和 end 的值,以记录当前最长回文串的位置。
- 返回结果:
- 最后,返回最长回文子串,即字符串中从 start 到 end 的子串。
代码实现
class Solution:
def expandAroundCenter(self, s, left, right):
"""
从给定的中心向两边扩展,寻找以给定中心为轴的最长回文串的左右边界。
Args:
s (str): 给定字符串
left (int): 回文串中心的左边界
right (int): 回文串中心的右边界
Returns:
tuple: 最长回文串的左右边界
"""
# 循环扩展,直到左右边界不满足回文串的条件
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
# 返回最长回文串的左右边界
return left + 1, right - 1
def longestPalindrome(self, s: str) -> str:
"""
寻找给定字符串中的最长回文子串。
Args:
s (str): 给定字符串
Returns:
str: 最长回文子串
"""
# 初始化最长回文子串的起始和结束位置
start, end = 0, 0
# 遍历字符串中的每个字符
for i in range(len(s)):
# 以当前字符为中心向两边扩展,得到以单个字符为中心的回文串的边界
left1, right1 = self.expandAroundCenter(s, i, i)
# 以当前字符和下一个字符的间隙为中心向两边扩展,得到以两个字符为中心的回文串的边界
left2, right2 = self.expandAroundCenter(s, i, i + 1)
# 如果以单个字符为中心的回文串更长,则更新最长回文串的起始和结束位置
if right1 - left1 > end - start:
start, end = left1, right1
# 如果以两个字符为中心的回文串更长,则更新最长回文串的起始和结束位置
if right2 - left2 > end - start:
start, end = left2, right2
# 返回最长回文子串
return s[start: end + 1]
复杂度分析
-
时间复杂度:O( n 2 n^2 n2),其中
n
是字符串的长度。长度为 1 和 2 的回文中心分别有n
和n−1
个,每个回文中心最多会向外扩展 O(n) 次。 -
空间复杂度:O(1)。