暴力破解,遍历所有子字符串,判断是否为回文字符串,返回最长的那个
时间复杂度 o ( n 3 ) o(n^{3}) o(n3)
肯定TLE
class Solution:
def longestPalindrome(self,s):
maxlength = 0
res = ""
for i in range(len(s)):
for j in range(i+1, len(s)+1):
if self.isPalindrome(s[i:j]):
if j-i+1 > maxlength:
maxlength = j-i+1
res = s[i:j]
return res
def isPalindrome(self,s):
if s[:(len(s)-1)//2+1] == s[len(s)//2:][::-1]:
return True
else:
return False
使用动态规划法,要求最大的回文子字符串,可以将其分解为子问题,考虑递推方程,用dp[i][j]表示s[i:j+1]是否为回文字符串(是为1不是为0),那么递推方程可以写成如下形式
dp[i][j] =1 if s[i] = s[j] and dp[i+1][j-1] =1
否则
dp[i][j] = 0
由递推方程我们可以知道j要从小到大遍历,i要从大到小。并且i<=j
这里要稍微注意一下的是,如果 i和j相邻,只需要判断s[i] 和s[j]是否相等即可,因为此时i+1>j-1
这种方法的时间复杂度为 o ( n 2 ) o(n^{2}) o(n2)
AC代码
class Solution:
"""
we use dp[i][j] to denote whether s[i:j+1] is palindrome or not
we can easily get the comprehension dp[i][j] = True if dp[i+1][j-1] is true and s[i] == s[j], it's not difficult
from the comprehension we can find that, i depend on i+1, j depend on j -1, that tell us how to definite the loop.
So the i should from lager to smaller and j should from smaller to larger.
And the other important thing is that , i and j should from be adjacent at init state because the large palindrome depend on short palindrome
"""
def longestPalindrome1(self, s):
if len(s) == 0:
return s
left, right = 0,0
dp = [[True if i == j else False for i in range(len(s))] for j in range(len(s))]
for j in range(len(dp)):
for i in range(j):
if j - i == 1:
dp[i][j] = True if s[i] == s[j] else False
else:
dp[i][j] = dp[i+1][j-1] and s[i] == s[j]
if dp[i][j] and j - i > right - left:
left, right = i, j
return s[left:right+1]
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
dp =[[0]*len(s) for i in range(len(s))]
left,right,maxer = 0,0,0
for j in range(len(s)):
for i in range(j,-1,-1):
if i == j:
dp[i][j] = 1
elif j - i == 1:
dp[i][j] = 1 if s[i] == s[j] else 0
else:
dp[i][j] = 1 if dp[i+1][j-1] == 1 and s[i] == s[j] else 0
if dp[i][j] == 1 and j - i + 1 > maxer:
maxer = j - i +1
left,right = i,j
return s[left:right+1]
simply
class Solution:
def longestPalindrome(self, s):
dp = [[0]*len(s) for i in range(len(s))]
left,right = 0,0
for i in range(len(dp)-1, -1,-1):
for j in range(i,len(dp)):
if i == j :
dp[i][j] = 1
else:
dp[i][j] =1 if (i+1 == j or dp[i+1][j-1] ==1) and s[i] == s[j] else 0
if dp[i][j] == 1:
if j - i > right - left:
left,right = i,j
return s[left:right+1]
beat 22%
因为回文字符串分为中心对称和周对称两种,所以我们可以从左往右依次遍历字符串s,并考虑周对称和中心对称两种情况,分别以s[i]
为中心,和以s[i]s[i+1]
为轴往外扩展,找到最大的回文字符串
这样做的时间复杂度小于最坏情况下是 o ( n 2 ) o(n^{2}) o(n2),最好情况下可以接近 o ( n ) o(n) o(n)
AC代码
class Solution1(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
self.res,self.left,self.right =1,0,0
for i in range(len(s)):
self.pivot(i,i,s)
self.pivot(i,i+1,s)
return s[self.left:self.right+1]
def pivot(self, i, j, s):
if j >= len(s):
return
if s[i] != s[j] :
return 0
while(i >=0 and j < len(s)):
if s[i] == s[j]:
i -=1
j +=1
else:
break
if j - i - 1 > self.res:
self.res = j - i - 1
self.left,self.right = i+1,j-1
beat61%