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

【数据结构与算法】力扣 5. 最长回文子串

题目描述

5. 最长回文子串

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

示例 1:

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

示例 2:

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

提示:

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

分析解答

最长回文子串:中心扩展法详解 🚀

我们采用 中心扩展法 来解决这个问题。这个方法利用了回文串的对称性质,通过从中心向两边扩展来查找最长的回文子串。


1. 回文字符串的特点
  • 回文串是对称的,比如:
    • "aba"(奇数长度,中心是 "b"
    • "abba"(偶数长度,中心是 "bb"
  • 回文一定有一个中心
    • 奇数回文:有 1 个中心字符,如 "racecar"(中心是 "e")。
    • 偶数回文:有 2 个中心字符,如 "abccba"(中心是 "cc")。

所以,我们可以 从每个字符出发,尝试以它为中心进行扩展,找到最长的回文子串。


2. 中心扩展法的核心思想
  1. 遍历字符串 s 中的每个字符 i

    • s[i] 为中心,扩展找到 奇数长度 的回文。
    • s[i]s[i+1] 为中心,扩展找到 偶数长度 的回文。
  2. 如何扩展?

    • left = iright = i(奇数回文)。
    • left = iright = i+1(偶数回文)。
    • s[left] === s[right] 时,不断 向两边扩展,直到 s[left] !== s[right] 为止。
  3. 记录最长回文的起点 start 和长度 maxLen,更新最大回文子串的范围。


3. 代码详细解析
function longestPalindrome(s) {
    if (s.length <= 1) return s; // 只有 1 个字符或空字符串,直接返回

    let start = 0, maxLen = 0; // 记录最长回文的起点和长度

    // 中心扩展函数,返回最长回文的起点和长度
    function expandAroundCenter(left, right) {
        while (left >= 0 && right < s.length && s[left] === s[right]) {
            left--;   // 左边扩展
            right++;  // 右边扩展
        }
        return [left + 1, right - left - 1]; // 起点 (left+1),长度 (right-left-1)
    }

    for (let i = 0; i < s.length; i++) {
        // 处理奇数长度回文
        let [oddStart, oddLen] = expandAroundCenter(i, i);
        if (oddLen > maxLen) {
            start = oddStart;
            maxLen = oddLen;
        }

        // 处理偶数长度回文
        let [evenStart, evenLen] = expandAroundCenter(i, i + 1);
        if (evenLen > maxLen) {
            start = evenStart;
            maxLen = evenLen;
        }
    }

    return s.substring(start, start + maxLen);
}

4. 代码执行流程解析

我们以 s = "babad" 为例,模拟执行过程:

Step 1: 遍历 s,每个字符作为中心

is[i]奇数扩展 (expandAroundCenter(i, i))偶数扩展 (expandAroundCenter(i, i+1))
0'b'"b"(长度 1)""(无回文)
1'a'"bab"(长度 3)""(无回文)
2'b'"aba"(长度 3)""(无回文)
3'a'"a"(长度 1)""(无回文)
4'd'"d"(长度 1)""(无回文)

Step 2: 选出最长回文

  • "bab""aba" 都是长度为 3 的回文。
  • maxLen = 3,最终返回 “bab”“aba”(都符合要求)。

5. 复杂度分析
  • 时间复杂度:O(n²)
    • 每个字符 i 都会触发一次 expandAroundCenter,最多扩展 O(n) 次,因此总共是 O(n²)
  • 空间复杂度:O(1)
    • 只使用了 startmaxLen 等变量,没有额外数组存储,空间复杂度是 常数级 O(1)

思路拓展

动态规划 O(n²) 也是可行的,但需要 O(n²) 的额外空间,而 中心扩展法更省空间O(1))。

动态规划 vs. 中心扩展

方法时间复杂度空间复杂度适用场景
动态规划O(n²)O(n²)适用于超长字符串
中心扩展法O(n²)O(1)推荐,空间更优

http://www.kler.cn/a/530683.html

相关文章:

  • 万字长文深入浅出负载均衡器
  • Hive之数据定义DDL
  • deepseek的两种本地使用方式
  • 算法随笔_37: 交替合并字符串
  • 使用朴素贝叶斯对自定义数据集进行分类
  • 小程序的协同工作与发布
  • [ VS Code 插件开发 ] 使用 Task ( 任务 ) 代替 createTerminal (终端) 来执行命令
  • 数据库和数据表的创建、修改、与删除
  • 冷启动+强化学习:DeepSeek-R1 的原理详解——无需监督数据的推理能力进化之路
  • 基于vue船运物流管理系统设计与实现(源码+数据库+文档)
  • 蓝桥杯学习笔记01
  • 【Qt】常用的容器
  • llama.cpp GGUF 模型格式
  • GWO优化SVM回归预测matlab
  • Mac怎么彻底卸载软件,简单彻底的卸载方式
  • 【数据结构-Trie树】力扣677. 键值映射
  • SQL/Panda映射关系
  • Spring Boot 2 快速教程:WebFlux处理流程(五)
  • 自制虚拟机(C/C++)(三、做成标准GUI Windows软件,扩展指令集,直接支持img软盘)
  • 轮转数组-三次逆置
  • Chromium132 编译指南 - Android 篇(六):从 Linux 版切换到 Android 版
  • 鸢尾花书《编程不难》02---学习书本里面的三个案例
  • 使用VCS进行单步调试的步骤
  • Scala语言的安全开发
  • Spring Bean 容器
  • 202周日复盘(159)本周回顾