每日算法 -【Swift 算法】寻找字符串中最长回文子串(三种经典解法全解析)

news2025/5/24 22:35:26

🧩 最长回文子串问题:三种经典解法全解析(含代码注释)

本文将系统讲解“最长回文子串”问题的三种常见解法:中心扩展法、动态规划、马拉车算法(Manacher’s Algorithm),并进行对比与总结。


📌 问题描述

给定一个字符串 s,返回其中 最长的回文子串

示例:

  • 输入:"babad"
  • 输出:"bab""aba"

✅ 解法一:中心扩展法(Expand Around Center)

🧠 思路

  • 回文的本质是“对称”
  • 遍历每个字符,尝试以它为中心向两边扩展,总共需要考虑 2n - 1 个中心(包括字符与字符之间的间隙)。
  • 需要对奇数长度(如 "aba")和偶数长度(如 "abba")分别处理

⏱ 复杂度

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

🧑‍💻 Swift 实现(含注释)

func longestPalindromeCenter(_ s: String) -> String {
    if s.isEmpty { return "" }

    let chars = Array(s)
    var start = 0, end = 0

    for i in 0..<chars.count {
        let len1 = expand(chars, left: i, right: i) // 奇数长度
        let len2 = expand(chars, left: i, right: i + 1) // 偶数长度
        let len = max(len1, len2)

        if len > end - start {
            start = i - (len - 1) / 2
            end = i + len / 2
        }
    }

    return String(chars[start...end])
}

func expand(_ chars: [Character], left: Int, right: Int) -> Int {
    var L = left, R = right
    while L >= 0 && R < chars.count && chars[L] == chars[R] {
        L -= 1
        R += 1
    }
    return R - L - 1 // 实际回文长度
}

✅ 解法二:动态规划(Dynamic Programming)

🧠 思路

  • 定义 dp[i][j] 表示 s[i...j] 是否为回文串。
  • 转移方程:
    • dp[i][j] = true if s[i] == s[j] && dp[i+1][j-1]

⏱ 复杂度

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

🧑‍💻 Swift 实现(含注释)

func longestPalindromeDP(_ s: String) -> String {
    let chars = Array(s)
    let n = chars.count
    if n < 2 { return s }

    var dp = Array(repeating: Array(repeating: false, count: n), count: n)
    var maxLen = 1
    var start = 0

    for i in 0..<n {
        dp[i][i] = true
    }

    for length in 2...n {
        for i in 0...(n - length) {
            let j = i + length - 1
            if chars[i] == chars[j] {
                if length == 2 {
                    dp[i][j] = true
                } else {
                    dp[i][j] = dp[i + 1][j - 1]
                }

                if dp[i][j] && length > maxLen {
                    maxLen = length
                    start = i
                }
            }
        }
    }

    return String(chars[start..<start + maxLen])
}

✅ 解法三:马拉车算法(Manacher’s Algorithm)

🧠 思路

  • 首先对字符串预处理,使得所有回文都是奇数长度(例如:"abba""#a#b#b#a#"
  • 使用数组 p[i] 记录以第 i 个字符为中心的最大回文“半径”
  • 利用已知的对称中心和边界进行跳跃扩展,从而实现线性时间复杂度

⏱ 复杂度

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

🧑‍💻 Swift 实现(含注释)

func longestPalindromeManacher(_ s: String) -> String {
    // Step 1: 预处理字符串,在每个字符中间加入 #
    let t = Array("#" + s.map { "\($0)#" }.joined())
    let n = t.count
    var p = Array(repeating: 0, count: n)

    var center = 0, right = 0
    var maxLen = 0, maxCenter = 0

    for i in 0..<n {
        let mirror = 2 * center - i // i 关于 center 的对称点

        // Step 2: 利用镜像对称性快速扩展
        if i < right {
            p[i] = min(right - i, p[mirror])
        }

        // Step 3: 尝试向左右扩展
        var a = i + p[i] + 1
        var b = i - p[i] - 1
        while a < n && b >= 0 && t[a] == t[b] {
            p[i] += 1
            a += 1
            b -= 1
        }

        // Step 4: 更新 center 和 right
        if i + p[i] > right {
            center = i
            right = i + p[i]
        }

        // Step 5: 更新最大值
        if p[i] > maxLen {
            maxLen = p[i]
            maxCenter = i
        }
    }

    // Step 6: 从原始字符串中提取结果
    let start = (maxCenter - maxLen) / 2
    let end = start + maxLen
    return String(s[s.index(s.startIndex, offsetBy: start)..<s.index(s.startIndex, offsetBy: end)])
}

🧪 示例输出

print(longestPalindromeCenter("babad"))   // 输出: "bab" 或 "aba"
print(longestPalindromeManacher("cbbd"))  // 输出: "bb"
print(longestPalindromeDP("babad"))  // "bab" 或 "aba"

📊 三种方法对比总结

算法时间复杂度空间复杂度实现难度适用场景
中心扩展法O(n²)O(1)⭐⭐ 易面试首选,简洁实用
动态规划O(n²)O(n²)⭐⭐⭐ 中等适用于变种题型
马拉车算法O(n)O(n)⭐⭐⭐⭐ 高性能关键、竞赛场景

✅ 最佳实践推荐

需求推荐方法
面试、日常开发、可读性✅ 中心扩展法
遇到类似子串变种问题✅ 动态规划
超大数据量、刷算法题、竞赛✅ 马拉车算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2384924.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

流程自动化引擎:重塑企业数字神经回路

在数字经济高速发展的今天&#xff0c;企业运营的核心逻辑正在经历一场静默的革命。流程自动化引擎作为这场变革的中枢神经系统&#xff0c;通过智能化的技术手段重构企业的业务逻辑与决策链路&#xff0c;将原本离散的“数字神经元”编织成高效协同的神经网络。这种技术不仅打…

nginx web服务日志分析

特点&#xff1a; 实时分析&#xff1a;支持实时分析 Nginx 日志&#xff0c;无需预先存储大量日志数据&#xff0c;能即时反馈网站的访问情况。轻量级高效&#xff1a;资源占用少&#xff0c;运行速度快&#xff0c;适合处理高流量网站的日志分析。多种输出格式&#xff1a;除…

VSCode+EIDE通过KeilC51编译,使VSCode+EIDE“支持”C和ASM混编

在使用Keil C51时&#xff0c;要让Keil C51支持混编则需要在混编的.c文件上右键选择Options for File *(ALTF7)&#xff0c;打开选项界面后&#xff0c;在 Properties 页 勾上 Generate Assembler SRC File 和 Assemble SRC File &#xff0c;如下图所示&#xff1a; 这样设置后…

游戏引擎学习第298天:改进排序键 - 第1部分

关于向玩家展示多个房间层所需的两种 Z 值 我们在前一天基本完成了为渲染系统引入分层 Z 值的工作&#xff0c;但还没有完全完成所有细节。我们开始引入图形渲染中的分层概念&#xff0c;即在 Z 轴方向上拥有多个独立图层&#xff0c;每个图层内部再使用一个单独的 Z 值来实现…

Mysql篇-优化

Mysql篇主要是纯理论的面试问题与技巧。 主要从以下进行开展&#xff1a; 索引相关问题&#xff1a; 1、Mysql如何定位慢查询&#xff1f; Mysql慢查询&#xff1a;某个业务查询数据响应时间过长或者与预期响应时间相差大。 表象&#xff1a;页面加载过慢、接口压测响应时间…

一文详解生成式 AI:李宏毅《生成式 AI 导论》学习笔记

生成式 AI 是怎么回事 人工智能&#xff08;Artificial Intelligence&#xff09; “智能”是一个广泛而复杂的概念&#xff0c;其定义和应用范围随着技术、科学和社会的发展不断演变。在当前的语境下&#xff0c;“智能”通常与人工智能&#xff08;AI&#xff09;相关联&am…

什么是物联网 (IoT):2024 年物联网概述

物联网&#xff08;IoT&#xff09;是一个有望彻底改变我们生活、工作以及与环境互动方式的概念。如今&#xff0c;越来越多的新兴企业和老牌企业都在利用物联网的力量创造创新产品与服务。正因为这一转变&#xff0c;互联互通已成为我们生活中不可或缺的一部分&#xff0c;科技…

8级-数组

前情回顾&#xff1a;在7级的时候&#xff0c;我们学习了如何定义、使用函数 目录 概念 什么是数组&#xff1f; 一维数组 声明 初始化 访问元素 计算数组长度 二维数组 声明 初始化 访问元素 思考 一维数组在内存中如何存储&#xff1f; 二维数组在内存中如何存储&…

大模型 Agent 就是文字艺术吗?

最近在技术圈里有一个很有趣的争论&#xff1a;大模型 Agent 是不是就是各种 Prompt 的堆叠&#xff1f;像 Manus 这样看起来很智能的 Agent&#xff0c;本质上是不是就是用巧妙的 Prompt 约束大模型生成更好的输出&#xff1f;换句话说&#xff0c;这是不是一门文字艺术&#…

YOLOv8检测头代码详解(示例展示数据变换过程)

本文旨在通过实例数据&#xff0c;详细解读YOLOv8检测头的网络结构及其代码实现。首先将从检测头的网络架构开始讲解&#xff0c;涵盖代码与网络结构图的对比分析。关键在于深入探讨检测头的输出结果&#xff0c;因为这些输出将直接用于损失函数的计算。由于在不同阶段&#xf…

JUC并发编程1

什么是juc 在java的java.util.concurrent包下的工具。 锁 传统的synchronize public class SealTicket {int total 50;public synchronized void seal() {if (total > 0) {System.out.println(Thread.currentThread().getName() "卖出第" (total--) "张…

STM32开发环境配置——VSCode+PlatformIO + CubeMX + FreeRTOS的集成环境配置

前言 为什么配置这样的一个环境呢&#xff1f;鄙人受够了Keil5那个简陋的工作环境了&#xff0c;实在是用不下去&#xff0c;调试上很容易跟CubeMX的代码产生不协调导致调试——发布代码不一致造成的一系列问题。CubeIDE虽说不错&#xff0c;但是它的代码辅助功能和构建系统实在…

Profibus转Profinet网关赋能鼓式硫化机:智能化生产升级的关键突破

在现代工业自动化领域&#xff0c;通讯协议转换器发挥着至关重要的角色。它们能够实现不同网络间的无缝对接和数据传输&#xff0c;确保了生产线上的设备可以顺畅地交流信息。今天&#xff0c;我们就来深入讨论开疆智能profibus转profinet网关KJ-PBM-PN以及其在鼓式硫化机中的应…

MongoDB 用户与权限管理完全指南

在当今数据驱动的时代&#xff0c;数据库安全已成为企业IT架构中最关键的环节之一。作为最受欢迎的NoSQL数据库之一&#xff0c;MongoDB提供了完善的用户认证和权限管理机制&#xff0c;但许多开发者和数据库管理员对这些功能的理解和应用仍停留在表面层次。本文将全面剖析Mong…

基于ITcpServer/IHttpServer框架的HTTP服务器

https://www.cnblogs.com/MuZhangyong/p/16839231.html 在基于ITcpServer/IHttpServer框架的HTTP服务器实现中,OnBody方法主要用于接收HTTP请求体数据,而触发HTTP响应通常是在OnMessageComplete方法中完成。以下是完整的响应触发机制说明: sequenceDiagramClient->>…

FPGA高效验证工具Solidify 8.0:全面重构图形用户界面

近日&#xff0c;FPGA高效验证工具Solidify发布了8.0版本。该版本对图形用户界面&#xff08;GUI&#xff09;进行了全面重构&#xff0c;历时两年&#xff0c;经过了大幅的架构改进&#xff0c;旨在为用户提供更安全、更稳定的使用环境。 Solidify的用户对隐私有严格要求&…

SIL2/PLd 认证 Inxpect毫米波安全雷达:3D 扫描 + 微小运动检测守护工业安全

Inxpect 成立于意大利&#xff0c;专注工业安全技术。自成立起&#xff0c;便致力于借助先进雷达技术提升工业自动化安全标准&#xff0c;解决传统安全设备在复杂环境中的局限&#xff0c;推出获 SIL2/PLd 和 UL 认证的安全雷达产品。 Inxpect 的雷达传感器技术优势明显。相较于…

2025电工杯数学建模A题思路数模AI提示词工程

我发布的智能体链接&#xff1a;数模AI扣子是新一代 AI 大模型智能体开发平台。整合了插件、长短期记忆、工作流、卡片等丰富能力&#xff0c;扣子能帮你低门槛、快速搭建个性化或具备商业价值的智能体&#xff0c;并发布到豆包、飞书等各个平台。https://www.coze.cn/search/n…

LLM | 论文精读 | NAACL 2025 | Clarify When Necessary:教语言模型何时该“问一句”再答!

&#x1f50d; 解读 NAACL 2025 重磅论文《Clarify When Necessary》&#xff1a;教语言模型何时该“问一句”再答&#xff01; &#x1f9e9; 一、现实问题&#xff1a;大模型“看不懂装懂”有多危险&#xff1f; 我们每天用的 ChatGPT、Claude 等大型语言模型&#xff08;LL…

嵌入式鸿蒙openharmony应用开发环境搭建与工程创建实现

各位小伙伴大家好,本周开始分享鸿蒙开发相关的内容,从基础的配置方法到各种功能的实现,探索国产操作系统的奥秘。 第一:观察结果 第二:开源语言 ArkTS是鸿蒙应用开发中使用的TypeScript超集,提供了一套丰富的API来构建应用界面和逻辑。 第三:环境搭建 步骤 1 通过如…