方法一:动态规划

思路与算法

对于一个子串而言,如果它是回文串,并且长度大于 2,那么将它首尾的两个字母去除之后,它仍然是个回文串。例如对于字符串“ababa”,如果我们已经知道“bab” 是回文串,那么 “ababa” 一定是回文串,这是因为它的首尾两个字母都是“a”。

根据这样的思路,我们就可以用动态规划的方法解决本题。我们用 P(i,j)表示字符串 s 的第 i 到 j 个字母组成的串(下文表示成 s[i:j])是否为回文串:

这里的「其它情况」包含两种可能性:

s[i, j]本身不是一个回文串;

i > j,此时 s[i,j] 本身不合法。

那么我们就可以写出动态规划的状态转移方程:

也就是说,只有 s[i+1:j-1] 是回文串,并且 s 的第 i 和 j个字母相同时,s[i:j] 才会是回文串。

上文的所有讨论是建立在子串长度大于 2 的前提之上的,我们还需要考虑动态规划中的边界条件,即子串的长度为 1 或 2。对于长度为 1 的子串,它显然是个回文串;对于长度为 2 的子串,只要它的两个字母相同,它就是一个回文串。因此我们就可以写出动态规划的边界条件:

根据这个思路,我们就可以完成动态规划了,最终的答案即为所有(即子串长度)的最大值。注意:在状态转移方程中,我们是从长度较短的字符串向长度较长的字符串进行转移的,因此一定要注意动态规划的循环顺序。

复杂度分析

时间复杂度:,其中 n 是字符串的长度。动态规划的状态总数为
 ,对于每个状态,我们需要转移的时间为 O(1)。

空间复杂度:,即存储动态规划状态需要的空间。

class Solution:def longestPalindrome(self, s: str) -> str:n = len(s)if n < 2:return smax_len = 1begin = 0# dp[i][j] 表示 s[i..j] 是否是回文串dp = [[False] * n for _ in range(n)]for i in range(n):dp[i][i] = True# 递推开始# 先枚举子串长度for L in range(2, n + 1):# 枚举左边界,左边界的上限设置可以宽松一些for i in range(n):# 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得j = L + i - 1# 如果右边界越界,就可以退出当前循环if j >= n:breakif s[i] != s[j]:dp[i][j] = False else:if j - i < 3:dp[i][j] = Trueelse:dp[i][j] = dp[i + 1][j - 1]# 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置if dp[i][j] and j - i + 1 > max_len:max_len = j - i + 1begin = ireturn s[begin:begin + max_len]

方案2:动态规划

这里,我们采用以空间换时间的动态规划策略,网上很多案例晦涩难懂,我们这里稍作改造。设我们的输入字符串为s:
1.构造二维矩阵dp,维度为len(s)*len(s),dp[left][right]表示子串s[left:right+1]是否为回文串,left和right均为下标索引,范围在0~len(s)之间,且left<right,因此dp矩阵中的每一个变量均为布尔量;
2.构造状态转移方程,考虑三种情况,
(1)left = right,当前子串只有一个字符,一定为回文串;
(2)right = left + 1,当前子串只有两个字符,判断这两个字符是否相等;
(3)right > left + 1,当前子串有多个字符,判断根据首位字符是否相等以及除去首位字符剩余子串是否为回文串判定当前子串。
状态转移方程为:

或者把前两种情况归类:

class Solution:def longestPalindrome(self, s):dp = [[False]*len(s) for _ in range(len(s))]max_start, max_len = 0, 0                       # 最长回文子串开始位置及长度for right in range(len(s)):                     # 右指针先走for left in range(right+1):                 # 左指针跟着右指针if right - left < 2:                    # 前两种情况dp[left][right] = (s[left] == s[right])else:                                   # 最后一种情况dp[left][right] = (s[left] == s[right]) and dp[left+1][right-1]# cur_substr = s[left:right+1]          # 当前考察的子串cur_len = right + 1 - left              # 当前子串长度为 right + 1 - leftif dp[left][right] and max_len < cur_len:max_start = leftmax_len = cur_lenreturn s[max_start:max_start + max_len]
class Solution:def longestPalindrome(self, s):dp = [[False]*len(s) for _ in range(len(s))]max_start, max_len= 0,0for right in range(len(s)):for left in range(right+1):if right -left<2:dp[left][right] = (s[left] == s[right])else:dp[left][right]= (s[left] ==s[right]) and dp[left+1][right -1]cur_len =right+1 -leftif dp[left][right] and max_len<cur_len:max_start =leftmax_len =cur_lenreturn s[max_start:max_start+max_len]
class Solution:def longestPalindrome(self,s):dp = [[False]*len(s) for _ in range(len(s))]max_start, max_len =0,0for right in range(len(s)):for left in range(right +1):if right -left<2:dp[left][right]=(s[left]==s[right])else:dp[left][right] = (s[left] == s[right]) and dp[left+1][right-1]cur_substr = s[left:right+1]if dp[left][right] and max_len <cur_len:max_start =leftmax_len =cur_lenreturn s[max_start:max_start + max_len]
class Solution:def longestPalindrome(self, s):dp = [[False]*len(s) for _ in range(len(s))]max_start, max_len =0,0for right in range(len(s)):for left in range(right+1):if right -left<2:dp[left][right] = (s[left] ==s[right])else:dp[left][right] = (s[left] == s[right]) and dp[left+1][right-1]cur_len = right +1 -leftif dp[left][right] and max_len<cur_len:max_start =leftmax_len =cur_lenreturn s[max_start: max_start+max_len]
class Solution:def longestPalindrome(self, s):dp = [[False]*len(s) for _ in range(len(s))]max_start, max_len =0,0for right in range(right +1):if right -left <2:dp[left][right] = (s[left] ==s[right])else:dp[left][right] = (s[left] == s[right]) and dp[left+1][right-1]cur_len = right +1 -leftif dp[left][right] and max_len<cur_len:max_start = leftmax_len = cur_lenreturn s[max_start:max_start + max_len]
class Solution:def longestPalindrome(self, s: str) -> str:n =len(s)if n<2:return smax_len =1begin =0#dp[i][j]表示s[i..j]是否回文串dp = [[False]* n for _ in range(n)]for i in range(n):dp[i][i] = Truefor L in range(2, n+1):for i in range(n):j = L+i-1if j>=n:breakif s[i] !=s[j]:dp[i][j] = Falseelse:if j-i<3:dp[i][j] = Trueelse:dp[i][j] = dp[i+1][j-1]if dp[i][j] and j-i+1 > max_len:max_len = j-i+1begin =1return s[begin:begin + max_len]
class Solution:def longestPalindrome(self, s: str) -> str:n = len(s)if n<2:return smax_len =1begin =0dp =[[False]* n for _ in range(n)]for i in range(2,n+1):for i in range(n):j = L+i-1if j>=n:break
class Solution:def longestPalindrome(self, s: str) -> str:n = len(s)if n< 2:return smax_len =1bigin = 0#dp[i][j]表示s[i...j]是否回文串dp = [[False] * n for _ in range(n)]for i in range(n):dp[i][i]= True#递推开始#先枚举子串长度for L in range(2, n+1):#先枚举左边界,左边界的上限设置可以宽松一些for i in range(n):#由L和i可以确定右边界,j-i+1=L        j =L+i-1#如果右边界越界,就可以退出当前循环if j>= n:breakif s[i] != s[j]:dp[i][j] = Falseelse:if j-i <3:dp[i][j] =Trueelse:dp[i][j] = dp[i+1][j-1]#只要dp[i][L] == true成立,就表示子串if dp[i][j] and j-i+1 > max_len:max_len = j-i+1begin =ireturn s[begin:begin + max_len]

2021-08-27最大回文子串 leetcode相关推荐

  1. 动态规划——最长回文子串(Leetcode 5)

    题目选自Leetcode 5 最长回文子串 力扣解题代码: class Solution { public:string longestPalindrome(string s) {int len=s. ...

  2. 动态游标for循环_【【动图算法】(动态规划篇):最长回文子串

    本周继续做一道动态规划类型的题目,该题是阿里一面的一道算法题. [动图算法](动态规划篇):最长回文子串 leetcode 5 题:最长回文子串 https://leetcode-cn.com/pro ...

  3. 【代码训练营】day56 | 647. 回文子串 516.最长回文子序列

    所用代码 java 回文子串 LeetCode 647 题目链接:回文子串 LeetCode 647 - 中等 思路 dp[i] [j]:[i, j]子串是否是回文子串,是回文就是true 递推公式: ...

  4. day04_ 最长回文子串 / 删除排序数组中的重复项

    day04 5. 最长回文子串 26. 删除排序数组中的重复项 ❗另:java中length,length(),size()区别 5. 最长回文子串 LeetCode链接 给定一个字符串 s,找到 s ...

  5. 最长回文子串与最长回文子序列

    文章目录 最长回文子串与最长回文子序列 最长回文子串 题目描述 dp解法 从中心扩展 马拉车算法 最长回文子序列 题目描述 dp 解法 递归思想 最长回文子串与最长回文子序列 最长回文子串 LeetC ...

  6. java 最长回文_【Java】【每日算法/刷穿 LeetCode】5. 最长回文子串(中等)

    首页 专栏 java 文章详情 0 [每日算法/刷穿 LeetCode]5. 最长回文子串(中等) 宫水三叶发布于 今天 12:00 题目描述 给你一个字符串 s,找到 s 中最长的回文子串. 示例 ...

  7. 刻意练习:LeetCode实战 -- Task17. 最长回文子串

    背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务.本期训练营采用分类别练习的模式,即选择了五个知识点(数组.链表.字符串.树.贪心算法),每个知 ...

  8. LeetCode实战:最长回文子串

    题目英文 Given a string s, find the longest palindromic substring in s. You may assume that the maximum ...

  9. LeetCode:Longest Palindromic Substring 最长回文子串

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  10. LeetCode 05最长回文子串

    题目描述 描述: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" ...

最新文章

  1. 我是如何有效的避免测试漏测?
  2. IBM已“弃疗”,AI医疗研发10年不赚钱,终于打算卖了
  3. 汇编语言--寄存器(cpu工作原理)
  4. linux作业控制三个,10个linux 作业控制的bash 脚本实例
  5. matlab工具箱中draw_graph不能用的解决方案
  6. Java并发编程包中atomic的实现原理
  7. MyEclipse的自动补全功能:输入@或者.没提示
  8. zabbix监控redis
  9. 如何使用线程完成售票系统
  10. ECMAScript:客户端脚本语言的标准
  11. SQL Server Management Studio 2016的新功能–滚动条
  12. Python可视化库Matplotlib的使用
  13. 手动实现读写锁(线程级)
  14. V2VNet: Vehicle-to-Vehicle Communication for Joint Perception and Prediction
  15. 夜的钢琴曲五—吉他指弹
  16. Oracle 变量绑定与变量窥视合集系列五
  17. C语言基于easyx的打字训练软件。
  18. PA、PB及RS功率计算
  19. putty使用方法~SSH等
  20. linux终端 中文是数字,Linux中man命令及之后的数字

热门文章

  1. whoosh读取+html,django-haystack+jieba+whoosh实现全文检索
  2. Oracle与MySQL的几点区别
  3. HttpApplication 类
  4. 操作SDO_GEOMETRY字段
  5. 会玩弹珠也可以拿来炫了?是的,这个技能燃爆了!
  6. 多线程之volatile关键字
  7. Hadoop2.7.4 HA centos6.8
  8. linux mysql 相关操作、问题
  9. Socket Tcp高密集信息广播转发强度测试
  10. CCNA培训课总结笔记--静态路由实现负载均衡(四)