LeetCode 5:最长回文子串(Longest Palindromic Substring)—— 题解

LeetCode 5:最长回文子串(Longest Palindromic Substring)题解

🔗 题目链接

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

📖 题目描述

给你一个字符串 s,找出其中最长的连续回文子串。若存在多个长度相同的最长回文子串,返回任意一个即可。

示例 1:

输入:s = "babad"

输出:"bab"

解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"

输出:"bb"

题目约束:

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

📌 题目核心考点

  • 经典 区间动态规划(区间DP) 题型
  • 字符串子串问题、回文判定进阶应用
  • 面试高频算法原题,重点考察DP状态定义、遍历顺序逻辑

💡 解题核心思路(DP解法)

暴力枚举所有子串再判断回文的方式时间复杂度为 O(n³),会超时。因此使用动态规划,复用已计算的子问题结果,将时间复杂度优化至 O(n²)。

一、状态定义

定义二维DP数组:

复制代码
dp[i][j] = 表示字符串区间 s[i...j] 是否为回文子串

true:是回文子串,false:不是回文子串

二、状态转移方程(核心)

回文子串的核心特性:两端字符相等,且中间包裹的子串也是回文

复制代码
if (s[i] == s[j]) {
    // 情况1:单个字符 / 两个相邻相同字符,一定是回文
    if (j - i <= 1) {
        dp[i][j] = true;
    } 
    // 情况2:区间长度大于2,依赖内部子串的结果
    else {
        dp[i][j] = dp[i + 1][j - 1];
    }
}

简单总结:首尾字符相同,且内部子串是回文,则当前区间是回文

三、关键遍历顺序(易错重点)

dp[i][j] 的状态依赖于 dp[i+1][j-1],因此遍历顺序固定:

  • i(左边界):从后往前遍历
  • j(右边界):从前往后遍历

该顺序保证:计算大区间时,内部小区间的子问题已经算完

复制代码
for (int i = len - 1; i >= 0; i--)
    for (int j = i; j < len; j++)

✅ 完整AC代码(修缮你的原代码)

java 复制代码
class Solution {
    public String longestPalindrome(String s) {
        // 初始最长长度为1,答案初始化为第一个字符(修复原代码空串BUG)
        int maxLen = 1;
        String ans = s.substring(0, 1);

        int len = s.length();
        char[] charArr = s.toCharArray();
        boolean[][] dp = new boolean[len][len];

        // 左边界倒序遍历
        for (int i = len - 1; i >= 0; i--) {
            // 右边界正序遍历
            for (int j = i; j < len; j++) {
                if (charArr[i] == charArr[j]) {
                    // 长度1、2直接回文
                    if (j - i <= 1) {
                        dp[i][j] = true;
                    } else {
                        // 长度大于2依赖内部
                        dp[i][j] = dp[i + 1][j - 1];
                    }

                    // 更新最长回文子串
                    if (dp[i][j] && (j - i + 1) > maxLen) {
                        maxLen = j - i + 1;
                        ans = s.substring(i, j + 1);
                    }
                }
            }
        }
        return ans;
    }
}

⏱️ 复杂度分析

指标 复杂度 说明
时间复杂度 O(n²) 两层循环枚举所有区间
空间复杂度 O(n²) 二维dp数组开销

💡 核心一句话总结

区间DP:首尾相等且内部子串回文 → 当前区间回文;逆序遍历左边界,保证子问题先解。

📝 面试高频追问(必背)

1. 为什么 i 必须倒序遍历?

dp[i][j] 依赖 dp[i+1][j-1],也就是当前行依赖下一行

只有 i 从后往前算,i+1 的结果才已经提前算好了。

2. 为什么要单独判断 j - i <= 1

当子串长度为 1、2 时,i+1 > j-1,没有内部子区间,不能走转移方程,需要手动初始化基准回文。

3. 可以优化空间吗?

可以。中心扩展法空间 O(1),时间同样 O(n²),是面试最优解。

需要我把中心扩展法的完整题解+代码也直接贴给你吗?

相关推荐
黄敬峰33 分钟前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术2 小时前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六5 小时前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术6 小时前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
Asize6 小时前
初识DFS 与 BFS:递归、队列与图遍历
算法
罗西的思考20 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
美团技术团队1 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl