Leetcode - 4 最长的回文串 python(动态规划 && 马拉车)

该博客探讨了如何使用动态规划解决LeetCode上的第4题——找到字符串中最长的回文子串。通过示例“babad”和“cbbd”,解释了输出“bab”和“bb”的原因。博主尝试了不同的解决方案,包括优化后的动态规划方法,尽管优化后的代码虽然简洁但时间效率稍低。
摘要由CSDN通过智能技术生成

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:

输入: “cbbd”
输出: “bb”

动态规划
class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s or len(s) == 1: return s
        def func(s, start, end):
            return s[start:end]
        
        out = ''
        maxlen = 0
        for i in range(len(s)):
            if i + maxlen // 2 > len(s): break
            start = i
            end = start + 1
            if end < len(s) and s[start] == s[end]:
                _end = end + 1
                _start = start
                _sub = s[_start:_end]
                while _start > 0 and _end < len(s) and s[_start - 1] == s[_end]:
                    _start -= 1
                    _end += 1
                    _sub = func(s, _start, _end)
                if len(_sub) > maxlen:
                    maxlen = len(_sub)
                    out = _sub
            sub = s[start:end]
            while start > 0 and end < len(s) and s[start - 1] == s[end]:
                start -= 1
                end += 1
                sub = func(s, start, end)
            if len(sub) > maxlen:
                maxlen = len(sub)
                out = sub
        return out

结果?????打扰了,代码也还有冗余的地方,还待优化
在这里插入图片描述
优化后(因为进行了偶数对称的预处理,所以时间长了一下,但是代码简洁一些【强迫症】)

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s or len(s) == 1: return s
        #preprocess
        data = '#'
        for i in range(len(s)):
            data += s[i] + '#'
        data += '#'
        
        out = ''
        maxlen = 0
        for i in range(len(data)):
            if i + maxlen // 2 > len(data): break
            start = i
            end = start + 1
            sub = data[start:end]
            while start > 0 and end < len(data) and data[start - 1] == data[end]:
                start -= 1
                end += 1
                sub = data[start:end]
            if len(sub) > maxlen:
                maxlen = len(sub)
                out = sub
        res = ''
        for i in range(len(out)):
            if out[i] != '#': res += out[i]
        return res

在这里插入图片描述

据说最好的马拉车

我是看这个博客的思路写的,大概是长这样
在这里插入图片描述

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s or len(s) == 1: return s
        #preprocess
        data = '#'
        for i in range(len(s)):
            data += s[i] + '#'
        print(data)

        def cal(string, center, le):
            length = le
            while (center-length-1) >= 0 and (center+length+1) < len(string) and string[center-length-1] == string[center+length+1]:
                length += 1
            return length

        iCenter = 0
        length = []
        length.append(cal(data, 0, 0))
        sub_left = iCenter - length[iCenter]
        sub_right = iCenter + length[iCenter]
        sub = data[0]
        for i in range(1, len(data)):
            length.append(0)
            _len = length[iCenter]
            iRight = iCenter + _len
            print('right', iRight, iCenter)
            if i < iRight - length[i]: #有镜像点时
                length[i] = min(iRight - i, length[2*iCenter - i]) #看看左边有没有溢出
                #print('1', length, i, sub)
            if i >= iRight - length[i]: 无镜像点时,或者左边溢出之后可能以i为中心能有更长的子串
                length[i] = cal(data, i, length[i])
                #print('2', length, i, sub)
            if length[i] > length[iCenter]:#比较一下长度
                iCenter = i
                sub_left = iCenter - length[iCenter]
                sub_right = iCenter + length[iCenter]
                sub = data[sub_left:sub_right+1]
                #print('3', length, i, sub, sub_left, sub_right)
        return sub[1::2]

调了很久 快了很多
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值