題目:給定一個(gè)字符串 s,找到 s 中最長(zhǎng)的回文子串(關(guān)于中心對(duì)稱(chēng))。你可以假設(shè) s 的最大長(zhǎng)度為 1000。
示例 1:
輸入: "babad"
輸出: "bab"
注意: "aba" 也是一個(gè)有效答案。
1.中心擴(kuò)散法
分析
子串的字符長(zhǎng)度數(shù)可能是奇數(shù)或者偶數(shù),所以可以是相鄰的字符相等(偶數(shù)個(gè)),或者中間隔一個(gè)相等(奇數(shù)個(gè)),因此如果遇到這樣的情況,就回頭看是否能夠?qū)﹂L(zhǎng)度擴(kuò)大。(注意邊界條件即可)時(shí)間復(fù)雜度為因?yàn)閮?nèi)部最多可以回溯到整個(gè)待搜索字符的長(zhǎng)度。
class Solution:
def longestPalindrome(self, s: str) -> str:
if len(s)<=1:
return s
i = 0
res = s[0]
while i <len(s)-1:
if s[i] == s[i+1]:
res1= self.backandforw(s,i,i+1)
if len(res1)>len(res):
res = res1
if i+2<len(s) and s[i] ==s[i+2]:
res1= self.backandforw(s,i,i+2)
if len(res1)>len(res):
res = res1
i+=1
return res
def backandforw(self,s,back,forw):
while back>0 and forw<len(s)-1 and s[back-1]==s[forw+1]:
back-=1
forw+=1
return s[back:forw+1]
2.動(dòng)態(tài)規(guī)劃法
動(dòng)態(tài)和規(guī)劃和遞歸類(lèi)似都要構(gòu)造可反復(fù)利用的結(jié)構(gòu)
這里就要找出前一步和后一步的關(guān)系
如果我們用二維數(shù)組來(lái)存儲(chǔ)結(jié)果,其中sign[i][j]表示從s[i]到s[j]是否是回文子串,那么sign[i-1][j+1]就可以用上一步的結(jié)果直接進(jìn)行判斷,而不用再去回溯了。邊界情況就是i=j,肯定是1的,以及i+1=j的時(shí)候,只需要判斷這一個(gè)字符相等即可賦值為1。但是這里要注意順序,從后往前是更好的思路。
動(dòng)態(tài)規(guī)劃的好處是可以存儲(chǔ)全部的回文子串。
class Solution:
def longestPalindrome(self, s):
sign = [[0 if i!=j else 1for i in range(len(s))] for j in range(len(s))]
longest = s[0]
for i in range(len(s)-1,-1,-1):
for j in range(len(s)-1,i,-1):
if s[i] == s[j]:
if i+1<=j-1 and sign[i+1][j-1]==1:
sign[i][j]=1
if 1+j-i>len(longest):
longest=s[i:j+1]
elif i+1==j:
sign[i][j]=1
if 1+j-i>len(longest):
longest=s[i:j+1]
return longest
動(dòng)態(tài)規(guī)劃要謹(jǐn)記的一點(diǎn),有時(shí)候并不需要一定要在最后一步得到結(jié)果,可以得到局部結(jié)果后,再去遍歷回顧。否則會(huì)在思維上造成構(gòu)造困難的局面,掉進(jìn)思維陷阱。