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

LeetCode算法日记 - Day 96: 最长回文子串

目录

1. 最长回文子串

1.1 题目解析

1.2 解法

1.3 代码实现


1. 最长回文子串

https://leetcode.cn/problems/longest-palindromic-substring/description/

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

示例 1:

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

示例 2:

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

提示:

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

1.1 题目解析

题目本质
这是一个子串搜索问题,要在字符串中找出最长的回文子串。本质上需要判断所有可能子串的回文性质,并记录最长的那个。核心挑战是"如何高效判断并找出最长回文"。

常规解法
最直观的想法:枚举所有可能的子串,对每个子串都进行回文判断,记录最长的。

// 常规解法:暴力枚举(可能超时)static class BruteForceSolution {public String longestPalindrome(String s) {int n = s.length();String longest = "";// 枚举所有子串for (int i = 0; i < n; i++) {for (int j = i; j < n; j++) {// 提取子串并判断是否为回文String sub = s.substring(i, j + 1);if (isPalindrome(sub) && sub.length() > longest.length()) {longest = sub;}}}return longest;}// 判断字符串是否为回文private boolean isPalindrome(String str) {int left = 0, right = str.length() - 1;while (left < right) {if (str.charAt(left) != str.charAt(right)) {return false;}left++;right--;}return true;}}

问题分析
暴力枚举的复杂度是 O(n³),当 n = 1000 时,10³ × 10³ × 10³ = 10⁹ 次操作,会超时。
关键观察:大回文串的判断依赖于小回文串

  • 判断 "abcba" 是否为回文时,需要先确认 "bcb" 是回文

  • 判断 "bcb" 是否为回文时,又需要确认 "c" 是回文

  • 存在大量重复判断,可以优化

思路转折
要想高效 → 必须避免重复判断 → 动态规划预处理所有子串
核心洞察:回文串的递推性质

  • 如果 s[i] == s[j],且 s[i+1..j-1] 是回文,那么 s[i..j] 也是回文

  • 可以从小区间推导到大区间

  • 预先计算所有子串的回文性质,顺便记录最长的

状态定义:dp[i][j] = s[i..j] 是否为回文

1.2 解法

算法思想
采用区间动态规划:

1. 定义 dp[i][j] = s[i..j] 是否为回文子串

2. 状态转移:

  • 单字符:dp[i][i] = true
  • 相邻字符:dp[i][i+1] = (s[i] == s[i+1])
  • 其他情况:dp[i][j] = (s[i] == s[j]) && dp[i+1][j-1]

3. 遍历顺序:i 从大到小(n-1 → 0),j 从小到大(i → n-1)

4. 过程中记录最长回文的起始位置和长度

步骤拆解

i)边界处理:长度小于2直接返回

ii)初始化:创建 boolean[][] dp,初始 begin=0, len=1

iii)填表:

  • 外层循环:i 从 n-1 倒序到 0

  • 内层循环:j 从 i 正序到 n-1

  • 判断 s[i] 是否等于 s[j]:

    • 相等 + 单字符(i==j)→ dp[i][j] = true

    • 相等 + 相邻(i+1==j)→ dp[i][j] = true

    • 相等 + 其他 → dp[i][j] = dp[i+1][j-1]

    • 不相等 → 保持 false

  • 若 dp[i][j] 为真且长度更长,更新 begin 和 len

iv)返回结果:s.substring(begin, begin+len)

易错点

  • 遍历顺序错误:必须 i 倒序(i-- 而不是 i++),因为 dp[i][j] 依赖 dp[i+1][j-1]。如果写成 i++ 会导致无限循环

  • 长度计算错误:区间 [i, j] 的长度是 j-i+1,不是 i-j+1。因为 j >= i(j在右边),写反会得到负数或0

  • begin 更新遗漏:找到更长回文时,必须同时更新 begin 和 len,否则起始位置和长度不匹配,导致提取错误的子串

  • 边界条件处理:相邻字符判断应该是 i+1 == j 或 j-i == 1,不要写成 i == j-1(虽然等价但容易混淆)。在这种情况下不能直接访问 dp[i+1][j-1],否则会越界

1.3 代码实现

// 最长回文子串
static class Solution {public String longestPalindrome(String s) {int n = s.length();if (n < 2) return s;  // 边界处理char[] ch = s.toCharArray();boolean[][] dp = new boolean[n][n];int begin = 0, len = 1;  // 初始化:至少有单字符// 填表:i 倒序,j 正序for (int i = n-1; i >= 0; i--) {for (int j = i; j < n; j++) {if (ch[i] == ch[j]) {// 首尾字符相等if (i == j) {dp[i][j] = true;  // 单字符} else if (i+1 == j) {dp[i][j] = true;  // 相邻字符} else {dp[i][j] = dp[i+1][j-1];  // 看内部}}// 首尾不等,保持 false// 更新最长回文if (dp[i][j] && j-i+1 > len) {begin = i;len = j-i+1;}}}return s.substring(begin, begin + len);}
}

复杂度分析

  • 时间复杂度:O(n²)

  • 空间复杂度:O(n²)

http://www.dtcms.com/a/581727.html

相关文章:

  • 汽车ECU诊断刷写和OTA升级中的验签和校验
  • 网站主题旁边的图标怎么做的套模板网站
  • x265 编码器Analysis::compressInterCU_rd0_4 函数详细分析
  • 小杰-大模型(two)——RAG与Agent设计——Langchain-prompt提示词
  • Rust 练习册 :Luhn Trait与Trait实现
  • 家庭机器人,从科幻到日常的二十年突围战
  • 网站html地图导航代码大全网站功能的介绍
  • Android开发(Kotlin) 高阶函数、内联函数
  • AI安全与网络安全的融合:从挑战到解决方案
  • 从零开始构建现代化React应用:最佳实践与性能优化
  • 国外的网站建设公司广州工商注册服务中心
  • 【tips】常用不同状态小圆点样式css
  • 保险微网站制作公司网站费用计入什么科目
  • SSM网上水果商城s7436(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 北京市建设信息网站湖南手机版建站系统信息
  • 【函数参数传递方式选择指南(C/C++)】
  • 做ppt的图片素材网站数字营销成功案例
  • 企业网站子页面模板网站 开发 外包
  • 机器学习日报14
  • 解决Mac不能识别#include <bits/stdc++.h> 头文件问题
  • 基于站点数据进行遥感机器学习参数反演-以XGBOOST反演LST为例(附带数据与代码)试读
  • 四面山网站建设现在帮别人做网站赚钱不
  • 破解EEG逆问题:ADMM-ESINet如何融合优化理论与深度学习实现实时源成像
  • CSS 高中低部分面试题方法及知识点介绍
  • GMI Cloud@AI周报 | Cursor 2.0发布自研模型Composer;小鹏发布新一代人形机器人 IRON
  • 莱芜手机网站建设报价网站建设平台策划
  • 【jmeter】-安装-插件安装
  • 猫头虎AI分享:CodeBuddy IDE 已支持 GLM-4.6!亲测更强了
  • 云手机能够流畅运行大型游戏吗
  • 【App开发】手机投屏的几种方式(含QtScrcpy)- Android 开发新人指南