当前位置: 首页 > news >正文

5. 最长回文子串

5. 最长回文子串

中等

提示

给你一个字符串s,找到s中最长的 回文 子串。

示例 1:

输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd" 输出:"bb"

提示:

  • 1 <= s.length <= 1000
  • s仅由数字和英文字母组成

📝 核心笔记:最长回文子串 (Center Expansion)

1. 核心思想 (一句话总结)

“投石问路:以每一个可能的中心点(单个字符或两个字符的间隙)为圆心,向两边同时扩散,直到碰到不一样的字符为止。”

  • 回文特性:中心对称。
  • 中心点:对于长度为 的字符串,共有 个中心( 个单字符中心, 个双字符间隙中心)。
  • 策略:枚举所有中心,向外while循环扩散。
2. 算法流程 (Split Loop Strategy)
  1. 奇数回文 (Odd)
    • 枚举i0n-1
    • 初始中心l = i,r = i(比如 "aba" 的 'b')。
  1. 偶数回文 (Even)
    • 枚举i0n-2
    • 初始中心l = i,r = i + 1(比如 "abba" 的中间缝隙)。
  1. 扩散 (Expand)
    • while (l >= 0 && r < n && s[l] == s[r]):只要不越界且字符相等,就继续l--,r++
  1. 记录 (Update)
    • 循环结束时,lr刚好停在第一个不匹配(或越界)的位置。
    • 真实长度(r - 1) - (l + 1) + 1=r - l - 1
    • 更新ansLeftansRight
🔍 代码回忆清单
// 题目:LC 5. Longest Palindromic Substring class Solution { public String longestPalindrome(String S) { char[] s = S.toCharArray(); // 转数组提速 int n = s.length; int ansLeft = 0; int ansRight = 0; // 记录最佳区间的左闭右开 [start, end) // 1. 情况一:奇数长度回文 (中心是 1 个字符) for (int i = 0; i < n; i++) { int l = i; int r = i; // 核心扩散逻辑 while (l >= 0 && r < n && s[l] == s[r]) { l--; r++; } // 循环结束时,l 和 r 都是"越界"或"不匹配"的位置 // 回文范围是 [l+1, r-1],长度 = r - l - 1 if (r - l - 1 > ansRight - ansLeft) { ansLeft = l + 1; ansRight = r; // 这里存 r 刚好符合 substring 的左闭右开 } } // 2. 情况二:偶数长度回文 (中心是 2 个字符之间) for (int i = 0; i < n - 1; i++) { int l = i; int r = i + 1; // 区别仅在于初始 r 的位置 while (l >= 0 && r < n && s[l] == s[r]) { l--; r++; } if (r - l - 1 > ansRight - ansLeft) { ansLeft = l + 1; ansRight = r; } } return S.substring(ansLeft, ansRight); } }
⚡ 快速复习 CheckList (易错点)
  • [ ]为什么长度是r - l - 1
    • 假设回文是 "bab",下标 1。扩散结束时l停在 -1 (越界),r停在 3 (越界)。
    • 直接相减3 - (-1) = 4是不对的。因为lr多走了一步。
    • 实际回文长度是(r-1) - (l+1) + 1,化简后就是r - l - 1
  • [ ]代码可以合并吗?
    • 可以。通常会提取一个expand(i, j)函数,分别调用expand(i, i)expand(i, i+1),避免代码重复。
  • [ ]时间复杂度?
    • 。每个中心向外扩散最多 步,共有个中心。
    • 相比 DP ( 空间),这种方法空间是 ,常数更小,实际运行非常快。
🖼️ 中文数字演练

S = "babad"

ansLeft=0,ansRight=0(初始长度0)

  1. 奇数扫描i=1('a'):
    • 初始l=1, r=1。匹配 ('a'=='a')。
    • 扩散l=0, r=2。匹配 ('b'=='b')。
    • 扩散l=-1, r=3。越界,停止。
    • 长度3 - (-1) - 1 = 3
    • 更新ansLeft=0,ansRight=3(即 "bab")。
  1. 奇数扫描i=2('b'):
    • 初始l=2, r=2。匹配。
    • 扩散l=1, r=3。'a' != 'a' ? 匹配 ('a'=='a')。
    • 扩散l=0, r=4。'b' != 'd'。不匹配,停止。
    • 长度4 - 0 - 1 = 3
    • 长度没超过之前的 3,不更新 (或者更新 "aba",长度一样)。
  1. 偶数扫描:
    • i=0('b', 'a'): 不匹配。
    • ...后续无更长。

最终结果: "bab" (或 "aba")。

📝 核心笔记:最长回文子串 (Unified Center Expansion)

1. 核心思想 (一句话总结)

“万物皆中心:不管是字符还是间隙,我都给它一个编号i。通过除法把编号还原成左右指针,一次循环搞定所有奇偶情况。”

  • 总中心数:长度为 的字符串,有 个中心点。
  • 映射公式
    • l = i / 2
    • r = (i + 1) / 2
    • i是偶数时,l == r(指向同一个字符,奇回文)。
    • i是奇数时,l + 1 == r(指向相邻字符,偶回文)。
2. 算法流程 (Unified Loop)
  1. 遍历 (Loop)
    • i0遍历到2 * n - 2(共2n - 1次)。
  1. 定位 (Locate)
    • 计算初始扩散点:lr
    • 例如i=0->0,0(char 0);i=1->0,1(gap 0-1);i=2->1,1(char 1)。
  1. 扩散 (Expand)
    • 标准中心扩散逻辑:while (s[l] == s[r])向两边炸开。
  1. 更新 (Update)
    • 计算长度r - l - 1
    • 如果比当前记录的长,更新ansLeftansRight
🔍 代码回忆清单
// 题目:LC 5. Longest Palindromic Substring class Solution { public String longestPalindrome(String S) { char[] s = S.toCharArray(); int n = s.length; int ansLeft = 0; int ansRight = 0; // 1. 统一遍历所有的"中心点" // N 个字符 + (N-1) 个间隙 = 2N - 1 个中心 for (int i = 0; i < 2 * n - 1; i++) { // 2. 核心映射技巧 // 偶数 i (0, 2...): l = k, r = k (单字符中心) // 奇数 i (1, 3...): l = k, r = k+1 (间隙中心) int l = i / 2; int r = (i + 1) / 2; // 3. 尝试扩散 while (l >= 0 && r < n && s[l] == s[r]) { l--; r++; } // 4. 记录最大值 // 此时回文区间是 (l, r),长度 r - l - 1 if (r - l - 1 > ansRight - ansLeft) { ansLeft = l + 1; ansRight = r; } } return S.substring(ansLeft, ansRight); } }
⚡ 快速复习 CheckList (易错点)
  • [ ]2 * n - 1的来源?
    • 想象字符串是a|b|c。字符有 3 个,竖线(间隙)有 2 个。加起来就是 个位置。
  • [ ]除法取整的妙用
    • i=0:0/2=0,1/2=0->(0, 0)
    • i=1:1/2=0,2/2=1->(0, 1)
    • 利用整数除法向下取整的特性,完美覆盖了两种情况。
  • [ ]效率怎么样?
    • 时间复杂度依然是 ,并没有变快,只是代码行数变少了。
    • 实际上,因为多了一些数学运算,可能会比分开写两个循环微微慢一点点(几乎可忽略)。
🖼️ 数字演练

S = "aba"(

, 循环04)

  1. i=0:l=0, r=0(中心 'a')。
    • 扩散后l=-1, r=1。长度 1 ("a")。记录。
  1. i=1:l=0, r=1(中心 'ab' 缝隙)。
    • s[0]!=s[1]。无法扩散。长度 0。
  1. i=2:l=1, r=1(中心 'b')。
    • 第一次:s[1]==s[1]('b').
    • 第二次:l=0, r=2,s[0]==s[2]('a'=='a').
    • 第三次:l=-1, r=3, 越界。
    • 长度3 - (-1) - 1 = 3("aba")。更新。
  1. i=3:l=1, r=2(中心 'ba' 缝隙)。
    • s[1]!=s[2]。无法扩散。
  1. i=4:l=2, r=2(中心 'a')。
    • 长度 1 ("a")。不更新。

最终结果: "aba"。

http://www.jsqmd.com/news/482287/

相关文章:

  • L2-025 分而治之
  • 1143. 最长公共子序列
  • 直租累、中介烦、托管香?房东出租模式“痛点热力图”实测
  • 【JAVA基础08】—— 关系运算符与逻辑运算符详解(附面试例题)
  • 6类宠物皮肤病目标检测数据集分享 | 宠物医疗(适用于YOLO系列深度学习检测任务)
  • MySQL 1045 登录失败,账号密码错误处理
  • 网站提示 403 Forbidden 是什么原因?怎么修
  • 交往理性:2001-2026——从对话伦理到自感伦理的思想谱系
  • 2026建网站一般需要多少钱?
  • 打开网站显示跳转不生效,仍可访问HTTP错误怎么办|已解决
  • 低代码/无代码的真相:是程序员的“终结者”,还是“超级外挂”?
  • 网站访问慢、卡半天,PHP 环境优化步骤
  • 奇葩编程赛极限救场:C++两行神操作,填平两次手滑大坑!
  • 基于 immich-go 的相册备份和 rename 脚本
  • 打开网站显示页面加载缓慢?错误怎么办|已解决
  • 宝塔面板网站迁移,从 A 服务器到 B 服务器
  • 香河婚介所的标尺与星光:一位IT工程师的平凡婚姻
  • 2026/3/15
  • 生物信息学常用编程语言选型:Python、R、Perl、Julia的应用场景与生态对比
  • 交易数据异常检测:大数据环境下的解决方案
  • 3月12日笔记
  • 基于烟花算法(FWA)及三次样条的机器人路径规划,50个场景任意选择附Matlab代码
  • 基于小波多尺度同步压缩变换WMSST结合MCNN多尺度卷积神经网络的故障诊断研究附Matlab代码
  • 2026年论文AI率92%怎么办?3招实测降到5%以下 - 还在做实验的师兄
  • 嘎嘎降AI怎么用?从注册到出结果手把手教你全流程 - 还在做实验的师兄
  • 2026年毕业季降AI工具哪家强?学姐帮你踩过坑了 - 还在做实验的师兄
  • 目标检测数据集 - 汽车损坏检测数据集下载
  • springboot基于JavaWeb的美食交流宣传系统
  • 打开网站显示常见问题与解决方案(新手必备)错误怎么办|已解决
  • 2026年论文降AI率工具怎么选?研究生亲测这5款最靠谱 - 还在做实验的师兄