便宜、量大,微軟 Xbox Series S 成黑五期間最火爆主機
給你一個字串 s,找到 s 中最長的迴文子串。
示例 1:
輸入:s = "babad"
輸出:"bab"
解釋:"aba" 同樣是符合題意的答案。
示例 2:
輸入:s = "cbbd"
輸出:"bb"
示例 3:
輸入:s = "a"
輸出:"a"
示例 4:
輸入:s = "ac"
輸出:"a"
提示:
1 <= s.length <= 1000
s 僅由數字和英文字母(大寫和/或小寫)組成
解法一:
對於字串abccba或者abcdcba,滿足s[i]==s[len(s)-1-i]時,字串被稱為迴文字串。
這個解法的缺點是執行時間很長。
def longestPalindrome(s): length= len(s) max_palindrome = None max_length = 0 for i in range(length): if (length-i)<=max_length: break for j in range(length-i): length_palindrome = (length - i) - j if length_palindrome<=max_length: break fork in range(length_palindrome): if s[i+k]==s[(length-1-j)-k]: if (((length-1-j)-k)-(i+k)) in [0,1]: if length_palindrome > max_length: max_palindrome = s[i:(i+length_palindrome)] max_length= length_palindrome break else: break return max_palindrome
解法二:
動態規劃
思路與演算法
對於一個子串而言,如果它是迴文串,並且長度大於 22,那麼將它首尾的兩個字母去除之後,它仍然是個迴文串。例如對於字串 \textrm{``ababa''}“ababa”,如果我們已經知道 \textrm{``bab''}“bab” 是迴文串,那麼 \textrm{``ababa''}“ababa” 一定是迴文串,這是因為它的首尾兩個字母都是 \textrm{``a''}“a”。
根據這樣的思路,我們就可以用動態規劃的方法解決本題。我們用 P(i,j)P(i,j) 表示字串 ss 的第 ii 到 jj 個字母組成的串(下文表示成 s[i:j]s[i:j])是否為迴文串:
這裡的「其它情況」包含兩種可能性:
那麼我們就可以寫出動態規劃的狀態轉移方程:
也就是說,只有 s[i+1:j-1]s[i+1:j−1] 是迴文串,並且 ss 的第 ii 和 jj 個字母相同時,s[i:j]s[i:j] 才會是迴文串。
上文的所有討論是建立在子串長度大於 22 的前提之上的,我們還需要考慮動態規劃中的邊界條件,即子串的長度為 11 或 22。對於長度為 11 的子串,它顯然是個迴文串;對於長度為 22 的子串,只要它的兩個字母相同,它就是一個迴文串。因此我們就可以寫出動態規劃的邊界條件:
根據這個思路,我們就可以完成動態規劃了,最終的答案即為所有(即子串長度)的最大值。注意:在狀態轉移方程中,我們是從長度較短的字串向長度較長的字串進行轉移的,因此一定要注意動態規劃的迴圈順序。
class Solution: def longestPalindrome(self, s: str) -> str: n = len(s) if n < 2: return s max_len = 1 begin = 0 # dp[i][j] 表示 s[i..j] 是否是迴文串 dp = [[False] * n for _ in range(n)] for i in range(n): dp[i][i] = True # 遞推開始 # 先列舉子串長度 for L in range(2, n + 1): # 列舉左邊界,左邊界的上限設定可以寬鬆一些 for i in range(n): # 由 L 和 i 可以確定右邊界,即 j - i + 1 = L 得 j = L + i - 1 # 如果右邊界越界,就可以退出當前迴圈 if j >= n: break if s[i] != s[j]: dp[i][j] = False else: if j - i < 3: dp[i][j] = True else: dp[i][j] = dp[i + 1][j - 1] # 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是迴文,此時記錄迴文長度和起始位置 if dp[i][j] and j - i + 1 > max_len: max_len = j - i + 1 begin = i return s[begin:begin + max_len]
解法原文:
https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode-solution/