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 马拉车算法就算了,看着都头疼

【2021-3-2】

思路4:双指针

分解问题:

  1. 寻找回文子串,从中间向两边扩散,需要考虑长度为奇偶
  2. 遍历字符串,不断更新最长的回文子串

代码段4:通过

class Solution:
    def longestPalindrome(self, s: str) -> str:
        res = ''
        def palindrome(s, l, r):
            while l >= 0 and r < len(s) and s[l] == s[r]:
                l -= 1
                r += 1
            return s[l+1:r]
        for i in range(len(s)):
            s1 = palindrome(s, i, i)
            s2 = palindrome(s, i, i+1)
            res = s1 if len(res) < len(s1) else res
            res = s2 if len(res) < len(s2) else res
        return res

总结:

  1. 仿佛找到了刷算法的乐趣,就得有一些套路熟记于心。
  2. 优雅的很

2021-3-30

来自牛客

# -*- coding:utf-8 -*-

class Solution:
    def getLongestPalindrome(self, A, n):
        def ishuiwen(a_str, l, r):
            while l >= 0 and r < len(a_str) and a_str[l] == a_str[r]:
                l -= 1
                r += 1
            return a_str[l+1:r]
        res = 0
        for i in range(n):
            huiwen1 = ishuiwen(A, i, i)
            huiwen2 = ishuiwen(A, i, i+1)
            res = max(res, len(huiwen1), len(huiwen2))
        return res

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值