题目内容
描述
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例:
- 示例1
1 | 输入: "babad" |
- 示例2
1 | 输入: "cbbd" |
解法1 —— 暴力法
我觉得这应该是最开始的想法吧,简单粗暴,两个指针把所有可能的子串都定出来,然后写个判断是否是回文的函数。缺点就是时间复杂度高咯,两重循环$O(n^2)$,再来个判断又是$O(n)$,总起来$O(n^3)$,空间复杂度$O(n)$。代码还是给一下。
1 | def longestPalindrome(self, s): |
解法2 —— 动态规划
If “aba” is a palindrome, is “xabax” and palindrome? Similarly is “xabay” a palindrome?
这个思路稍微想一下也能想到。既然aba是回文,那xabay怎么判断呢?这个时候动态规划就派上用场了,我们定义:
动态转移方程如下:
再说一下,动态规划的那张表其实只要填一半,填表的顺序如下图所示
最后找出p[row][col]==1,并且|row-col|最大的那个子串就ok。
1 | def longestPalindrome(self, s): |
不过还是时间超限了。时间复杂度$O(n^2)$,空间复杂度$O(n^2)$。
解法3 —— 中心枚举法
该解法代码参考自:https://blog.csdn.net/asd136912/article/details/78987624。
根据自己的理解修改了代码,主要思路和动态规划扩展的向左右思路一致,要分奇数和偶数分别寻找,AC。
delta就是试探过程中回文的半径1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
n=len(s)
if n==0:
return ""
maxPalindromeLen = 1
maxPalindrome = s[0]
for i in range(n):
# 子串长度为奇数时
delta=1
while(i-delta>=0 and i+delta<n):
if s[i-delta]==s[i+delta]:
# 下一次试探的试探长度加1
delta+=1
else:
break
# 试探长度减1,delta就是当前i为中心点,左右扩展的长度
delta-=1
if 2*delta+1>maxPalindromeLen:
maxPalindromeLen=2*delta+1
maxPalindrome=s[i-delta:i+delta+1]
# 子串长度为偶数时,将s[i]和s[i+1]视为绑定
# 分别向s[i]的左边和s[i+1]的右边试探
# 最开始delta要初始化为0,因为需要比较s[i]和s[i+1]
delta=0
if (i+1<n):
while(i-delta>=0 and i+1+delta<n):
if s[i-delta]==s[i+1+delta]:
delta+=1
else:
break
delta-=1
if 2*delta+2>maxPalindromeLen:
maxPalindromeLen=2*delta+2
maxPalindrome=s[i-delta:i+1+delta+1]
return maxPalindrome
解法4 —— Manacher算法
算法详细介绍 https://articles.leetcode.com/longest-palindromic-substring-part-ii/
时间复杂度$O(n)$ ,空间复杂度$O(n)$
1 | def longestPalindrome(self, s): |
要注意的地方
python截取字符串,
从下标begin到下标end截取时,str[begin:end+1]
join函数和replace函数的使用
二维“数组”的创建(实质上是嵌套的List)