一. 题目
-
题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 -
示例
二. 方法一: 暴力求解
-
解题思路
-
解题代码
# 判断字符串是否为回文 def palindrome(self, s1: str): s2 = s1[::-1] if s1 == s2: return True else: return False def longestPalindrome(self, s: str) -> str: len1 = len(s) len2 = len(s) while len2 >= 1: for l in range(0, len1 - len2 + 1): if self.palindrome(s[l: l + len2]): return s[l: l + len2] len2 -= 1 return ""
-
分析
时间复杂度: O(n^3)
空间复杂度: O(1)
三. 方法二: 动态规划
-
动态规划:
- 一个字符串是否为回文串 取决于:
a. 首尾两个字符相等
b. 去掉首尾两字符后是回文串 - 子串从一个字符开始循环遍历, 如果其两侧想当, 就将两侧的字符并入子串
- 遍历完整个字符串, 获取到最长子串的长度 和 其起始的下标索引
- 返回该最长子串即可
- 一个字符串是否为回文串 取决于:
-
解题代码
def longestPalindrome(s: str) -> str: size = len(s) # 创建一个二维列表, 并将所有的元素赋值为False arr = [[False for _ in range(size)] for _ in range(size)] # index: 表示最长回文子串的起始下标索引 index = 0 # max_len: 表示最长回文子串的长度 max_len = 1 # 二维列表的对角线设置为True, 表示长度为1的子串均是回文串 for i in range(size): arr[i][i] = True # for j in range(0, size): for i in range(0, j): # 如果两侧的字符相等 if s[i] == s[j]: # 如果字符串的长度小于3, 则一定是回文串 if j - i < 3: arr[i][j] = True # 如果字符串的长度不小于3, 则其是否为回文串取决于去掉两侧字符后的子串 else: arr[i][j] = arr[i + 1][j - 1] # 如果两侧字符不相等, 则一定不是回文串 else: arr[i][j] = False # 如果该子串为回文串 if arr[i][j]: # 获取当前子串的长度 cur_len = j - i + 1 # 如果当前子串的长度超过了之前的最长子串长度 if cur_len > max_len: # 获取最长子串的长度及其起始下标索引 max_len = cur_len index = i return s[index: index + max_len]
-
分析
时间复杂度: O(n^2)
空间复杂度: O(n^2)
四. 方法三: 中心扩散法
-
解题思路
- 从头开始遍历整个字符串
- 然后判断该子串两侧的元素是否相等, 并记录该子串的长度和起始下标索引
- 如果两侧元素相等, 扩展子串, 得到的子串都是回文串, 并修改其长度即起始下标索引
-
解题代码
def longestPalindrome(s: str) -> str: # 记录最长回文子串的起始和终止下标索引 start, end = 0, 0 for i in range(len(s)): # 从当前字符所在下标向两侧同时扩充 l1, r1 = expandAroundCenter(s, i, i) # 从当前字符及右侧字符(两者相等时)向两侧同时扩充 l2, r2 = expandAroundCenter(s, i, i + 1) # 返回最长回文子串的开始下标索引和结束下标索引 if r1 - l1 > end - start: start, end = l1, r1 if r2 - l2 > end - start: start, end = l2, r2 # 返回最长回文子串 return s[start: end + 1] # 扩充函数 def expandAroundCenter(s: str, left: int, right: int): # 如果子串两侧元素两侧的字符相等, 则子串向两侧同时扩充 # 直到两侧不相等位置 while left >= 0 and right < len(s) and s[left] == s[right]: left -= 1 right += 1 # 返回能扩充到的最长子串 return left + 1, right - 1
-
分析
时间复杂度: O(n^2)
空间复杂度: O(1)