LeetCode0005. 最长回文子串

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

  2. 示例

    在这里插入图片描述

二. 方法一: 暴力求解
  1. 解题思路

  2. 解题代码

    # 判断字符串是否为回文
    def palindrome(self, s1: str):
    	s2 = s1[::-1]
        if s1 == s2:
            return True
        else:
            return False
    
    def longestPalindrome(self, s: str) -> str:
        len1 = len(s)
        len2 = len(s)
        while len2 >= 1:
            for l in range(0, len1 - len2 + 1):
                if self.palindrome(s[l: l + len2]):
                    return s[l: l + len2]
            len2 -= 1
        return ""
    
  3. 分析

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

三. 方法二: 动态规划
  1. 动态规划:

    1. 一个字符串是否为回文串 取决于:
      a. 首尾两个字符相等
      b. 去掉首尾两字符后是回文串
    2. 子串从一个字符开始循环遍历, 如果其两侧想当, 就将两侧的字符并入子串
    3. 遍历完整个字符串, 获取到最长子串的长度 和 其起始的下标索引
    4. 返回该最长子串即可
  2. 解题代码

    def longestPalindrome(s: str) -> str:
    	size = len(s)
    	# 创建一个二维列表, 并将所有的元素赋值为False
        arr = [[False for _ in range(size)] for _ in range(size)]
        # index: 表示最长回文子串的起始下标索引
        index = 0
        # max_len: 表示最长回文子串的长度
        max_len = 1
        # 二维列表的对角线设置为True, 表示长度为1的子串均是回文串
        for i in range(size):
            arr[i][i] = True
    	# 
        for j in range(0, size):
            for i in range(0, j):
            	# 如果两侧的字符相等
                if s[i] == s[j]:
                	# 如果字符串的长度小于3, 则一定是回文串
                    if j - i < 3:
                        arr[i][j] = True
                    # 如果字符串的长度不小于3, 则其是否为回文串取决于去掉两侧字符后的子串
                    else:
                        arr[i][j] = arr[i + 1][j - 1]
                # 如果两侧字符不相等, 则一定不是回文串
                else:
                    arr[i][j] = False
    			# 如果该子串为回文串
                if arr[i][j]:
                	# 获取当前子串的长度
                    cur_len = j - i + 1
                    # 如果当前子串的长度超过了之前的最长子串长度
                    if cur_len > max_len:
                    	# 获取最长子串的长度及其起始下标索引
                        max_len = cur_len
                        index = i
    
        return s[index: index + max_len]
    
  3. 分析
    时间复杂度: O(n^2)
    空间复杂度: O(n^2)

四. 方法三: 中心扩散法
  1. 解题思路

    1. 从头开始遍历整个字符串
    2. 然后判断该子串两侧的元素是否相等, 并记录该子串的长度和起始下标索引
    3. 如果两侧元素相等, 扩展子串, 得到的子串都是回文串, 并修改其长度即起始下标索引
  2. 解题代码

    def longestPalindrome(s: str) -> str:
    	# 记录最长回文子串的起始和终止下标索引
    	start, end = 0, 0
        for i in range(len(s)):
        	# 从当前字符所在下标向两侧同时扩充
            l1, r1 = expandAroundCenter(s, i, i)
            # 从当前字符及右侧字符(两者相等时)向两侧同时扩充
            l2, r2 = expandAroundCenter(s, i, i + 1)
            # 返回最长回文子串的开始下标索引和结束下标索引
            if r1 - l1 > end - start:
                start, end = l1, r1
            if r2 - l2 > end - start:
                start, end = l2, r2
       	# 返回最长回文子串
        return s[start: end + 1]
    
    # 扩充函数
    def expandAroundCenter(s: str, left: int, right: int):
    	# 如果子串两侧元素两侧的字符相等, 则子串向两侧同时扩充
    	# 直到两侧不相等位置
        while left >= 0 and right < len(s) and s[left] == s[right]:
            left -= 1
            right += 1
        # 返回能扩充到的最长子串
        return left + 1, right - 1
    
  3. 分析
    时间复杂度: O(n^2)
    空间复杂度: O(1)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值