思路一:暴力(超时)
用一个函数专门判断是否是回文,然后枚举所有子串,不断更新max_len
复杂度n^3,双循环n*n,判断回文n
class Solution:
# 暴力匹配(超时)
def longestPalindrome(self, s: str) -> str:
# 特判
size = len(s)
if size < 2:
return s
max_len = 1
res = s[0]
# 枚举所有长度大于等于 2 的子串
for i in range(size - 1):
for j in range(i + 1, size):
if j - i + 1 > max_len and self.__valid(s, i, j):
max_len = j - i + 1
res = s[i:j + 1]
return res
def __valid(self, s, left, right):
# 验证子串 s[left, right] 是否为回文串
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
思路二:动态规划----状态转移情况
回文:
- 如果一个字符串的头尾两个字符都不相等,那么这个字符串一定不是回文串;
- 如果一个字符串的头尾两个字符相等,才有必要继续判断下去。
- 1、如果里面的子串是回文,整体就是回文串;
- 2、如果里面的子串不是回文串,整体就不是回文串。
定义状态:dp[i][j]
表示子串 s[i…j] 是否为回文子串
状态转移方程:dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]
边界条件是:表达式 [i + 1, j - 1]
不构成区间,即长度严格小于 2,即 j - 1 - (i + 1) + 1 < 2
,整理得 j - i < 3
。
只要一得到 dp[i][j] = true
,就记录子串的长度和起始位置
复杂度:n^2
class Solution:
def longestPalindrome(self, s: str) -> str:
l=len(s)
if l<2:
return s
#初始化n*n矩阵表示每一段子序列
dp = [[False for _ in range(l)] for _ in range(l)]
max_len = 1
start = 0
for j in range(1,l):
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]#状态转移公式
else:
dp[i][j]=False
#记录最大
if dp[i][j]:
if j-i+1>max_len:
max_len=j-i+1
start=i
return s[start:start + max_len]