LeetCode 5. 最长回文子串

题目描述

参考解法

方法一:暴力解法

遍历所有的子串,判断是否为回文字符串

class Solution:
    def longestPalindrome(self, s: str) -> str:
        if len(s) < 2:
            return s
        begin = 0
        maxlength = 1
        for i in range(len(s)-1):
            for j in range(i+1, len(s)):
                if (j - i + 1 > maxlength) and self.isPalindrome(s, i, j):
                    maxlength = j - i + 1
                    begin = i
        return s[begin: begin+maxlength]


    def isPalindrome(self, chararray: str, left: 'begin index', right: 'end index') -> bool:
        while (left < right):
            if chararray[left] != chararray[right]:
                return False
            left += 1
            right -= 1
        return True

复杂度分析

  • 时间复杂度: O ( n 3 ) O(n^3) O(n3)
  • 空间复杂度: O ( 1 ) O(1) O(1)

但此解法超出时间限制

方法二:中心扩展算法

遍历字符串中的字符,分别以每个字符、每个字符和下一个字符为中心向两边扩散,寻找最长回文子串。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        if len(s) < 2:
            return s
        begin = 0
        maxlength = 1
        for i in range(len(s)-1):
            oddLen = self.expandAroundCenter(s, i, i)
            evenLen = self.expandAroundCenter(s, i, i + 1)
            maxCurlength = max(oddLen, evenLen)
            if maxCurlength > maxlength:
                maxlength = maxCurlength
                begin = i - (maxCurlength - 1) // 2
        return s[begin: begin + maxlength]


    def expandAroundCenter(self, chararray: str, left: 'left center index', right: 'right center index') -> int:
        length = len(chararray)
        while (left >= 0 and right < length):
            if chararray[left] == chararray[right]:
                left -= 1
                right += 1
            else:
                break
        PalindromeLen = right - left - 1    # right - left + 1 - 2
        return PalindromeLen

执行结果

复杂度分析复杂度分析

方法三:动态规划

动态规划
状态转移矩阵

class Solution:
    def longestPalindrome(self, s: str) -> str:
        length = len(s)
        if length < 2:
            return s
        begin = 0
        maxlength = 1
        Palindrome_Matrix = [[False] * length for _ in range(length)]

        for i in range(length):
            Palindrome_Matrix[i][i] = True  # 对角线表示的是单个字符,肯定是回文串

        # 先按列,再按行赋值
        for j in range(1, length):
            for i in range(j):
                if s[i] == s[j]:
                    # 若s[i...j]的长度≤3,则一定为回文串
                    if j - i < 3:
                        Palindrome_Matrix[i][j] = True
                    else:
                        Palindrome_Matrix[i][j] = Palindrome_Matrix[i+1][j-1]

                if Palindrome_Matrix[i][j] and (j - i + 1 > maxlength):
                    begin = i
                    maxlength = j - i + 1

        return s[begin: begin + maxlength]

执行结果

复杂度分析
复杂度分析

*方法四:Manacher 算法

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

        # 预处理字符串
        new_s = self.adddivider(s, '#')
        new_length = len(new_s)
        # 回文半径
        p = [0 for i in range(new_length)]
        # 当前已得到的通过中心扩散法能够扩散到的最右边的下标
        maxRight = 0
        # maxRight对应的中心点下标
        center = 0

        begin = 0
        maxlength = 1

        for i in range(new_length):
            if i < maxRight:
                # i关于center的对称点
                mirror = 2 * center - i
                # 状态转移方程
                p[i] = min(maxRight - i, p[mirror])

            # 尝试使用中心扩散法,更新p[i]的值,注意这一步是与 i > maxRight 的情况结合起来
            left = i - (p[i] + 1)
            right = i + (p[i] + 1)
            while(left >= 0) and (right < new_length) and (new_s[left] == new_s[right]):
                p[i] += 1
                left -= 1
                right += 1

            if i + p[i] > maxRight:
                maxRight = i + p[i]
                center = i

            if p[i] > maxlength:
                maxlength = p[i]
                begin = (i - maxlength) // 2

        return s[begin: begin + maxlength]
        
        
    def adddivider(self, s: str, divider: str) -> str:
        new_s = divider
        for i in range(len(s)):
            new_s += (s[i] + divider)
        return new_s

在这里插入图片描述

复杂度分析
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值