回文,顧名思義就是段字元顛倒過來和它本身是相同的。如abcba和abba,正著讀反著讀都是它本身。在leetcode上關於回文的題我們將在這裡進行乙個總結。回文問題大多用動態規劃和雙指標指標來解決
判斷乙個字串是不是回文子串其實只要比較s和s[::-1]就可以實現。但是問題是每次都會給你附加一些其他的。
第125題:驗證回文串(簡單)
在判斷這個字串的時候我們需要之前進行如下工序:
1.去除無關的字元,我們用re正規表示式可以輕易完成。注意的是正則結果要轉換成字串型別。
2.全體變成小寫,我們用s.lower()完成。
import re
clean = re.findall('[a-za-z0-9]+',s)
clean = ''.join(clean)
clean = clean.lower()
print(clean)
l = len(clean)-1
if clean == clean[::-1]:
return true
else:
return false
驗證回文字串 ⅱ(簡單)
開始加入了其他條件:最多刪除乙個字元。
我們需要想通刪除乙個字元意味著什麼。在這道題中,刪除乙個字元意味著在雙指標的迴圈中第一次遇到兩邊指標所指字元不同時,有一次機會跳過左側或者右側指標所指的、不相同的字元。
def validpalindrome(self, s: str) -> bool:
if s == s[::-1]: #如果是回文直接返回
return true
l,r = 0,len(s)-1 #lr分別是字串的頭和尾巴
while l第131題分割回文串(中等)
本題的問題在於我們需要把乙個字串拆分成多個回文串,那麼一定會有多種模式。我們能夠直接想到的就是拆分成每乙個字元,因為單個字元本身就是回文串。想發現帶有兩個字元組成的回文串的分割方式,裡面或許還需要參雜著單個字元的模式——畢竟兩兩分割可能還真無法分割完所有的字元,例如這個aab,aa是回文而b卻不是;那麼三個呢?三個字元分割這個字串裡面勢必又包含兩個字元和單個字元的模式。我們能夠感覺到這種從子問題到父問題的解決方案應該是「動態規劃」或者是「遞迴」。那麼這道題,這兩種方案都可以,我們以遞迴為例。
def dfs(s, path, res)
這裡設定的引數
s:遞迴處理的字串
path:第乙個for迴圈代表尋找以某一模式開頭進行的迴圈。path用來儲存這一模式最後獲得的結果。如尋找乙個遞迴的字元是下圖綠色標註的a、b、b、a,如果尋找兩個遞迴的字元開頭的是ab但是由於ab不是回文串所以沒有後續遞迴。
res:res記錄全部的結果
黃色的bb是這樣找到的:首先尋找1字元開頭的模式,找到a是回文,進行遞迴1-1:繼續找到1字元開頭的模式(綠色圓圈的分支)這個模式走完後,進行遞迴1-2:找到2個字元開頭的模式,找到bb,進行遞迴1-2-1:找到1個字元開頭的模式,找到a。這時候因為s為空所以將path加入到res中。過程中,用path儲存找到的回文串並傳遞下去。
**如下:
s = "abba"
def dfs(s, path, res):
if not s:
return
for i in range(len(s)):
if s[:i+1] == s[i::-1]:
dfs(s[i+1:], path+[s[:i+1]], res)
tmp,res = ,
dfs(s, tmp, res)
res
最長回文子串
給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。
示例 1:
輸入: 「babad」
輸出: 「bab」
注意: 「aba」 也是乙個有效答案。
顯然動態規劃依然是我們良好的選擇,雖然有著複雜度為n的馬拉車演算法,還是動態規劃更好理解而且具有萬用性。雖然它的複雜度要高一些。
我們這樣定義我們的dp陣列:它表示第i個到第j個字元是否是回文子串。
這樣定義之後,j一定是在i和字串長度len之間的。我們這樣更新我們的dp:
1.左上角到右下角全部置1,含義是每個字元是它自己的回文子串。
2.從外層的i從1開始進行遍歷,內層的j從0開始遍歷到i,意義是逐列填滿所有到i行的內容,如果ij位置對應的字元是相等的,那麼dp[j][i] = dp[j+1][i-1],意義是去掉兩側相等的字元是否是回文串。當然如果ij的距離為1我們直接可以判斷是回文串,因為它是兩個相同字元相連的樣子。
3.dp更新完畢後,我們取盡量靠近右上角的dp為1的元素,因為右上角代表著j盡量小,i盡量大,如此我們可以找到最長的回文子串。
**:
dp = [[0 for _ in range(len(s))] for _ in range(len(s))]
for i in range(len(s)):
dp[i][i]=1
for i in range(1,len(s)):
for j in range(i):
if s[j]==s[i]:
if abs(i-j)<=1:
dp[j][i] = 1
else:
dp[j][i] = dp[j+1][i-1]
m_dis = 0
output = ""
for i in range(len(s)):
for j in range(i,len(s)):
if dp[i][j] == 1 and (abs(j-i)>m_dis or m_dis ==0):
m_dis = abs(j-i)
output = s[i:j+1]
output
用這個圖來參考一下吧。
leetcode 最長回文子串
給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為1000。示例 1 輸入 babad 輸出 bab 注意 aba 也是乙個有效答案。示例 2 輸入 cbbd 輸出 bb 中心拓展法 由乙個中心點開始向兩邊拓展,檢測邊界,判斷兩個值是否相等,相等則繼續拓展下去,檢測邊界。1....
最長回文子串(LeetCode)
給定乙個字串s,找到s中最長的回文子串。你可以假設s的最大長度為 1000。示例 1 輸入 babad 輸出 bab 注意 aba 也是乙個有效答案。示例 2 輸入 cbbd 輸出 bb class solution def longestpalindrome self,s type s str r...
LeetCode 最長回文子串
中文版 英文版的直接把 cn 刪除就可以訪問了 接下來是題目描述 給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。示例 1 輸入 babad 輸出 bab 注意 aba 也是乙個有效答案。示例 2 輸入 cbbd 輸出 bb 首先,我們看到題目以後的想法是什麼呢...