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 马拉车算法就算了,看着都头疼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章