leetcode【中等】5、最长回文子串

在这里插入图片描述
思路一:暴力(超时)
用一个函数专门判断是否是回文,然后枚举所有子串,不断更新max_len
复杂度n^3,双循环n*n,判断回文n

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

思路二:动态规划----状态转移情况
回文:

  • 如果一个字符串的头尾两个字符都不相等,那么这个字符串一定不是回文串;
  • 如果一个字符串的头尾两个字符相等,才有必要继续判断下去。
  • 1、如果里面的子串是回文,整体就是回文串;
  • 2、如果里面的子串不是回文串,整体就不是回文串。

定义状态:dp[i][j] 表示子串 s[i…j] 是否为回文子串

状态转移方程:dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]

边界条件是:表达式 [i + 1, j - 1] 不构成区间,即长度严格小于 2,即 j - 1 - (i + 1) + 1 < 2 ,整理得 j - i < 3

只要一得到 dp[i][j] = true,就记录子串的长度和起始位置

复杂度:n^2

class Solution:
    def longestPalindrome(self, s: str) -> str:
        l=len(s)

        if l<2:
            return s

        #初始化n*n矩阵表示每一段子序列
        dp = [[False for _ in range(l)] for _ in range(l)]

        max_len = 1
        start = 0

        for j in range(1,l):
            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]:
                    if j-i+1>max_len:
                        max_len=j-i+1
                        start=i
        
        return s[start:start + max_len]

猜你喜欢

转载自blog.csdn.net/qq_40707462/article/details/112439138