1. 程式人生 > 資訊 >便宜、量大,微軟 Xbox Series S 成黑五期間最火爆主機

便宜、量大,微軟 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 for
k 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/