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

LeetCode5最长回文子串

回文串起始位置公式 start = i - (maxLen-1)/2 详解

1. 问题背景

在最长回文子串算法中,我们使用中心扩展法找到回文串后,需要确定其在原字符串中的起始位置。已知:

  • i:扩展中心位置
  • maxLen:找到的最长回文串长度

核心问题:如何根据中心位置和长度,推导出起始位置公式 start = i - (maxLen-1)/2

2. 关键变量含义详解

2.1 变量定义

  • i:当前扩展的中心位置索引
    • 对于奇数长度回文串:i 就是回文串的中心字符位置
    • 对于偶数长度回文串:i 是左侧中心位置(两个中心字符中较左的那个)
  • maxLen:当前找到的最长回文串的长度
  • start:最长回文串在原字符串中的起始位置
  • exp(s, l, r):中心扩展函数,返回以 (l,r) 为中心的最长回文串长度

2.2 扩展函数解析

int exp(String s, int l, int r) {int n = s.length();while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {--l;  // 向左扩展++r;  // 向右扩展}return r - l - 1;  // 返回回文串长度
}

为什么返回 r - l - 1

  • 循环结束时,s[l] ≠ s[r] 或越界
  • 此时 lr 指向回文串外侧
  • 回文串实际范围是 [l+1, r-1]
  • 长度 = (r-1) - (l+1) + 1 = r - l - 1

3. 公式推导过程

3.1 核心思想

回文串具有轴对称特性:

回文串: [左半部分] [中心] [右半部分]←------ 对称轴 ------→

3.2 数学推导

步骤1:分析回文串结构
  • 总长度:maxLen
  • 中心位置:i
  • 问题:从中心位置如何找到起始位置?
步骤2:计算中心左侧字符数

对于长度为 maxLen 的回文串:

  • 奇数长度(如长度5):a b c b a
    • 中心字符:1个
    • 左侧字符数:(5-1)/2 = 2
  • 偶数长度(如长度4):a b b a
    • 中心字符:0个(中心在两字符间)
    • 左侧字符数:(4-1)/2 = 1(整数除法)

统一公式:中心左侧字符数 = (maxLen-1)/2

步骤3:计算起始位置

起始位置 = 中心位置 - 中心左侧字符数

start = i - (maxLen-1)/2

4. 可视化演示

4.1 测试用例设计

我们选择字符串 "babac" 进行完整演示,这个用例能覆盖算法的所有分支:

字符串: "babac"
索引:    0 1 2 3 4
字符:    b a b a c

4.2 完整执行过程

初始状态
maxLen = 0, start = 0
i = 0 时的处理
len1 = exp(s, 0, 0);  // 奇数中心扩展
len2 = exp(s, 0, 1);  // 偶数中心扩展

奇数扩展 exp(0, 0)

初始: l=0, r=0, s[0]='b'
检查: s[0] == s[0] ✓
扩展: l=-1, r=1
检查: l<0 ✗
返回: r-l-1 = 1-(-1)-1 = 1

偶数扩展 exp(0, 1)

初始: l=0, r=1, s[0]='b', s[1]='a'  
检查: s[0] != s[1] ✗
返回: r-l-1 = 1-0-1 = 0

更新状态

len = max(1, 0) = 1
maxLen < len? 0 < 1 ✓
maxLen = 1
start = 0 - (1-1)/2 = 0 - 0 = 0
i = 1 时的处理

奇数扩展 exp(1, 1)

初始: l=1, r=1, s[1]='a'
检查: s[1] == s[1] ✓  
扩展: l=0, r=2
检查: s[0]='b', s[2]='b', s[0] == s[2] ✓
扩展: l=-1, r=3
检查: l<0 ✗
返回: r-l-1 = 3-(-1)-1 = 3

偶数扩展 exp(1, 2)

初始: l=1, r=2, s[1]='a', s[2]='b'
检查: s[1] != s[2] ✗
返回: r-l-1 = 2-1-1 = 0  

更新状态

len = max(3, 0) = 3
maxLen < len? 1 < 3 ✓  
maxLen = 3
start = 1 - (3-1)/2 = 1 - 1 = 0

验证结果

回文串 = s.substring(0, 0+3) = "bab"
i = 2, 3, 4 的处理

继续处理后续位置,但都不会找到更长的回文串,所以最终结果保持不变。

4.3 关键步骤可视化

当 i=1, maxLen=3 时的推导:
原字符串: b a b a c
索引:     0 1 2 3 4↑   ↑   start  i   回文串 "bab":
- 中心位置: i = 1
- 长度: maxLen = 3  
- 中心左侧字符数: (3-1)/2 = 1
- 起始位置: start = 1 - 1 = 0验证:
字符串: b a b a c
索引:   0 1 2 3 4[---]start=0, length=3提取: s.substring(0, 3) = "bab"

5. 算法分支覆盖分析

5.1 代码分支识别

for (int i = 0; i < n; i++) {int len1 = exp(s, i, i);     // 分支1: 奇数长度扩展int len2 = exp(s, i, i + 1); // 分支2: 偶数长度扩展  int len = Math.max(len1, len2);if (maxLen < len) {          // 分支3: 更新最长回文串maxLen = len;start = i - (maxLen-1)/2; // 关键公式}
}

5.2 用例 “babac” 的分支覆盖

i奇数扩展(len1)偶数扩展(len2)max(len1,len2)是否更新覆盖分支
01011,2,3
13031,2,3
21011,2
31011,2
41011,2

结论:用例 “babac” 成功覆盖了所有代码分支。

6. 记忆技巧

6.1 视觉记忆法

回文串想象成一个天平:左边     |中心|     右边↑       ↑        ↑(len-1)/2  支点   (len-1)/2从支点往左数 (len-1)/2 步 = 起始位置
中心位置是i,占据了一个位置,想象代码计算回文串expandAroundCenter(i,i),expandAroundCenter(i,i+1)
(len-1)/2的1是中心占据的位置,所以i-左边长度就是start,因此有
start=i-(maxLen-1)/2

6.2 公式记忆口诀

  1. 回文对称:回文串关于中心轴对称
  2. 左右等分:除去中心,左右各有 (len-1)/2 个字符
  3. 向左偏移:从中心向左偏移 (len-1)/2 就是起始位置

6.3 快速验证法

给定 startmaxLen

  1. 提取字符串:s.substring(start, start + maxLen)
  2. 检查长度:应等于 maxLen
  3. 检查回文:提取的字符串应是回文串

7. 常见错误分析

7.1 错误公式1:start = i - maxLen/2

错误原因:没有考虑中心字符

  • 对于奇数长度,中心字符不应计入左侧
  • 正确应该是 (maxLen-1)/2

7.2 错误公式2:start = i - len1/2start = i - len2/2

错误原因:混淆了扩展长度和最终长度

  • 应该使用 maxLen(最长回文串长度)
  • 而不是单次扩展的长度

7.3 边界错误

问题start 可能为负数
解决:在实际应用中需要检查边界

start = Math.max(0, i - (maxLen-1)/2);

8. 完整算法总结

public String longestPalindrome(String s) {int maxLen = 0;    // 最长回文串长度int n = s.length();int start = 0;     // 最长回文串起始位置for (int i = 0; i < n; i++) {// 尝试奇数长度回文串(以i为中心)int len1 = expandAroundCenter(s, i, i);// 尝试偶数长度回文串(以i,i+1为中心)  int len2 = expandAroundCenter(s, i, i + 1);int len = Math.max(len1, len2);if (len > maxLen) {maxLen = len;// 核心公式:中心位置减去左侧字符数start = i - (maxLen - 1) / 2;}}return s.substring(start, start + maxLen);
}private int expandAroundCenter(String s, int left, int right) {while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {left--;right++;}return right - left - 1;
}

9. 总结

公式 start = i - (maxLen-1)/2 的本质

  1. i 是回文串的中心位置
  2. (maxLen-1)/2 是中心左侧的字符数量
  3. 从中心向左偏移左侧字符数量,就得到起始位置

记忆要点

  • 回文串是轴对称的
  • 知道中心和半径,就能确定起始位置
  • (maxLen-1)/2 就是回文串的"半径"

这个公式适用于所有情况(奇数/偶数长度),是一个优雅而实用的数学推导结果。


文章转载自:

http://PdkfQ6Ys.tfmrt.cn
http://732o0t8C.tfmrt.cn
http://mPdHIOvp.tfmrt.cn
http://H0OVSPvf.tfmrt.cn
http://56ODd7vs.tfmrt.cn
http://TUmZmvJX.tfmrt.cn
http://AxJ5iNhK.tfmrt.cn
http://XdWPCCHJ.tfmrt.cn
http://ILWZuPDG.tfmrt.cn
http://oBNoty18.tfmrt.cn
http://5K68B40I.tfmrt.cn
http://nd1S75TT.tfmrt.cn
http://mYKYHOFt.tfmrt.cn
http://YYDJKg79.tfmrt.cn
http://xs8UzNlZ.tfmrt.cn
http://IDVsSSkF.tfmrt.cn
http://DKpoS5zL.tfmrt.cn
http://pkdHvSve.tfmrt.cn
http://jEzhLTvN.tfmrt.cn
http://2iz98aRu.tfmrt.cn
http://zydUPvyW.tfmrt.cn
http://LhwHRz7I.tfmrt.cn
http://nPxsDWGG.tfmrt.cn
http://N5OfXYYA.tfmrt.cn
http://G08HVOgy.tfmrt.cn
http://q3w1GpqP.tfmrt.cn
http://3rlqrQ49.tfmrt.cn
http://uaetCrXa.tfmrt.cn
http://Lc47o4YZ.tfmrt.cn
http://aR8Yau2L.tfmrt.cn
http://www.dtcms.com/a/370037.html

相关文章:

  • Coze源码分析-资源库-编辑提示词-前端源码
  • 《sklearn机器学习——聚类性能指标》Contingency Matrix(列联表)详解
  • 小米笔记本电脑重装C盘教程
  • Linux RCU (Read-Copy-Update) 机制深度分析
  • 贪心算法应用:柔性制造系统(FMS)刀具分配问题详解
  • WSL Ubuntu Docker 代理自动配置教程
  • 基于Scikit-learn集成学习模型的情感分析研究与实现
  • MySQL数据库精研之旅第十七期:深度拆解事务核心(下)
  • Scikit-learn Python机器学习 - 特征降维 压缩数据 - 特征选择 - 单变量特征选择 SelectKBest - 选择Top K个特征
  • 从挑西瓜到树回归:用生活智慧理解机器学习算法
  • LabVIEW无线预警喷淋系统
  • Redis 的三种高效缓存读写策略!
  • 安装MATLAB205软件记录
  • Day28 打卡
  • 【FastDDS】XTypes Extensions
  • 软考 系统架构设计师系列知识点之杂项集萃(142)
  • 【音视频】H264编码参数优化和cbr、vbr、crf模式设置
  • 软考 系统架构设计师系列知识点之杂项集萃(141)
  • 竞价代运营:百度竞价账户托管优化
  • Python实战:爬取百度热搜榜,制作动态可视化报告
  • Windows 设备音频录制 | WASAPI 音频数据采集 / 环回录制
  • uniapp新增页面及跳转配置方法
  • 西门子S7-200 SMART PLC:编写最基础的“起保停”程序
  • UDP-Server(2)词典功能
  • 最大似然估计:损失函数的底层数学原理
  • 今日分享:C++ -- list 容器
  • 报错:OverflowError: Python integer 4294967296 out of bounds for uint32
  • 贪心算法应用:蛋白质折叠问题详解
  • AI-调查研究-71-具身智能 案例分析:从ROS到Tesla Optimus的开源与商业化实践
  • 【嵌入式C语言】七