https://leetcode-cn.com/problems/longest-palindromic-substring/
1. 题目
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
示例 1:
输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd" 输出: "bb"
2.想法
思考:看到题目什么也想不出来。还是看答案!
3.解法
3.1暴力破解
时间复杂度为 O ( N 3 ) O(N^{3}) O(N3),空间复杂度为 O ( 1 ) O(1) O(1)
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
size = len(s)
if size < 2:
return s
max_len = 1
res = s[0]
for i in range(size - 1):
for j in range(i + 1, size):
if j - i + 1 > max_len and self._value(s, i, j):
max_len = j - i + 1
res = s[i:j + 1]
return res
#验证子串是否为回文串
def _value(self, s, i, j):
while i < j:
if s[i] != s[j]:
return False
else:
i += 1
j -= 1
return True
3.2动态规划
我也想到了dp[i,j]=dp[i+1,j-1] and s[i]==s[j] 来进行状态转移。但是没有想到怎么初始化和输出(再定义一个变量保存数据,而不是输出dp)。
要多思考填表,自底而上!!!!!
根据状态转移公式得知,数据的方向是↙的,这样的推论要想正确,箭头数据必须是先得到的。那么如果顺序排列,那么箭头的就是最先进入求的数据。所以求数据的顺序就是
1 | 3 |
---|---|
2 | 4 |
2↙3 , 我们先求2然后得到3,正确。
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
#定义dp[i][j] 为子串s[i][j]是否为回文子串
size=len(s)
dp=[[False for _ in range(size)] for _ in range(size)]
for i in range(size):
dp[i][i]=True
max_len=1
start=0
for j in range(1,size):
for i in range(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]:
cur_len=j-i+1
if cur_len>max_len:
max_len=cur_len
start=i
return s[start:start+max_len]
2 | 4 |
---|---|
1 | 3 |
1↙4,我们先求1,然后得到4,正确。
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
#定义dp[i][j] 为子串s[i][j]是否为回文子串
size=len(s)
dp=[[False for _ in range(size)] for _ in range(size)]
for i in range(size):
dp[i][i]=True
max_len=1
start=0
for j in range(1,size):
for i in range(j-1,-1,-1):
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]:
cur_len=j-i+1
if cur_len>max_len:
max_len=cur_len
start=i
return s[start:start+max_len]
4 | 3 |
---|---|
2 | 1 |
2↙3,我们先求2,然后得到3,正确。
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
#定义dp[i][j] 为子串s[i][j]是否为回文子串
size=len(s)
dp=[[False for _ in range(size)] for _ in range(size)]
for i in range(size):
dp[i][i]=True
max_len=1
start=0
for i in range(size-2,-1,-1):
for j in range(size-1,i,-1):
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]:
cur_len=j-i+1
if cur_len>max_len:
max_len=cur_len
start=i
return s[start:start+max_len]
3 | 4 |
---|---|
1 | 2 |
1↙4,我们先求1,然后得到4,正确。
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
#定义dp[i][j] 为子串s[i][j]是否为回文子串
size=len(s)
dp=[[False for _ in range(size)] for _ in range(size)]
for i in range(size):
dp[i][i]=True
max_len=1
start=0
for i in range(size-2,-1,-1):
for j in range(i+1,size):
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]:
cur_len=j-i+1
if cur_len>max_len:
max_len=cur_len
start=i
return s[start:start+max_len]
https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/
3.3中心扩散法
我也想到了中心法,但是没想清楚怎么区分回文串是奇数还是偶数的情况,所以放弃了。现在是把两种情况都计算一次,合计最大的子串就是结果。
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
#定义dp[i][j] 为子串s[i][j]是否为回文子串
size=len(s)
max_len=1
res=s[0]
for i in range(size):
palindrome_odd, odd_len = self.__center_spread(s, size, i, i)
palindrome_even, even_len = self.__center_spread(s, size, i, i + 1)
#合并两种情况
cur_max_sub = palindrome_odd if odd_len >= even_len else palindrome_even
if len(cur_max_sub)>max_len:
max_len=len(cur_max_sub)
res=cur_max_sub
return res
def __center_spread(self, s, size, left, right):
i=left
j=right
while i>=0 and j<size and s[i]==s[j]:
i-=1
j+=1
return s[i+1:j],j-i-1