leetcode 5. longest-palindromic-substring 最長迴文子串 python3

時間:2020-6-21

題目地址:https://leetcode-cn.com/problems/longest-palindromic-substring/

題目難度:Medium

題目描述:

給定一個字符串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度爲 1000。

示例 1:

輸入: "babad"
輸出: "bab"
注意: "aba" 也是一個有效答案。
示例 2:

輸入: "cbbd"
輸出: "bb"


思路1:暴力破解

代碼段1:45/103 超時 天呀

from collections import Counter
class Solution:
    def longestPalindrome(self, s: str) -> str:
        result = ""
        a = Counter(list(s))
        print(a)
        for i, j in sorted(a.items(), key=lambda r:r[1], reverse=True):
            temp, result_0= [],  ""
            for x, y in enumerate(s):
                if y == i:
                    temp.append(x)
            print(temp)
            for p in temp:
                for q in temp:
                    print(p)
                    print(q)
                    print(s[p:q + 1])
                    if(s[p:q + 1] == (s[p:q + 1])[::-1]):
                        result_0 = s[p:q + 1] if len(result_0) < (q + 1 - p ) else result_0
            print(result_0)
            print("=======")
            print(result)
            if not result or len(result) <= len(result_0):
                result = result_0 
            print(result)
        return result

總結:

  1. 今天提交了考試的資料,身體也不太舒服,明天繼續整吧
  2. 下邊的是別人的暴力,只有一個用例超時,優秀
class Solution:
    # 暴力匹配(超時)
    def longestPalindrome(self, s: str) -> str:
        # 特判
        size = len(s)
        if size < 2:
            return s

        max_len = 1
        res = s[0]

        # 枚舉所有長度大於等於 2 的子串
        for i in range(size - 1):
            for j in range(i + 1, size):
                if j - i + 1 > max_len and self.__valid(s, i, j):
                    max_len = j - i + 1
                    res = s[i:j + 1]
        return res

    def __valid(self, s, left, right):
        # 驗證子串 s[left, right] 是否爲迴文串
        while left < right:
            if s[left] != s[right]:
                return False
            left += 1
            right -= 1
        return True

思路2:動態規劃

代碼段2:通過

class Solution:
    def longestPalindrome(self, s: str) -> str:
        size = len(s)
        if size < 2:
            return s

        dp = [[False for _ in range(size)] for _ in range(size)]

        max_len = 1
        start = 0

        for i in range(size):
            dp[i][i] = True

        for j in range(1, size):
            for i in range(0, j):
                if s[i] == s[j]:
                    if j - i < 3:
                        dp[i][j] = True
                    else:
                        dp[i][j] = dp[i + 1][j - 1]
                else:
                    dp[i][j] = False

                if dp[i][j]:
                    cur_len = j - i + 1
                    if cur_len > max_len:
                        max_len = cur_len
                        start = i
        return s[start:start + max_len]

總結:

  1. 還是不行呀,動態規劃,簡直是噩夢
  2. 寫完代碼可以在紙上畫下表格,填上代碼運行的過程

思路3:中心擴散

代碼段3:通過

class Solution:
    def longestPalindrome(self, s: str) -> str:
        size = len(s)
        if size < 2:
            return s

        # 至少是 1
        max_len = 1
        res = s[0]

        for i in range(size):
            palindrome_odd, odd_len = self.__center_spread(s, size, i, i)
            palindrome_even, even_len = self.__center_spread(s, size, i, i + 1)

            # 當前找到的最長迴文子串
            cur_max_sub = palindrome_odd if odd_len >= even_len else palindrome_even
            if len(cur_max_sub) > max_len:
                max_len = len(cur_max_sub)
                res = cur_max_sub

        return res

    def __center_spread(self, s, size, left, right):
        """
        left = right 的時候,此時迴文中心是一個字符,迴文串的長度是奇數
        right = left + 1 的時候,此時迴文中心是一個空隙,迴文串的長度是偶數
        """
        i = left
        j = right

        while i >= 0 and j < size and s[i] == s[j]:
            i -= 1
            j += 1
        return s[i + 1:j], j - i - 1

總結:

  1. 暴力是基礎,動態優化必須掌握,擴散中心得會寫,競賽級別的Manacher's Algorithm 馬拉車算法就算了,看着都頭疼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章