【LeetCode 热题100】字符串 DP 三连:最长回文子串、最长公共子序列 & 编辑距离(力扣5 / 1143/ )(Go语言版)

简介: 本文详细解析了字符串动态规划(DP)领域的三个经典问题:**最长回文子串**(LeetCode 5)、**最长公共子序列**(LeetCode 1143)和**编辑距离**(LeetCode 72)。通过定义状态、推导状态转移方程,结合 Go 语言实现代码,深入浅出地讲解了解题思路。从判断子串是否为回文到求解两个字符串的匹配长度,再到计算字符串转换的最小操作数,每道题都展示了 DP 的核心思想与应用场景。最后通过表格总结对比三题的异同,帮助读者更好地掌握字符串 DP 的解题技巧。

✨ 字符串 DP 三连:最长回文子串、最长公共子序列 & 编辑距离(LeetCode 5 / 1143 / 72)

  • 🔁 5. 最长回文子串
  • 📏 1143. 最长公共子序列
  • ✂️ 72. 编辑距离

1️⃣ 最长回文子串(LeetCode 5)

📌 题目描述

给你一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。


🧠 解题思路:动态规划

✅ 状态定义

dp[i][j] 表示子串 s[i...j] 是否是回文串。

🔁 状态转移方程

  • 如果 s[i] == s[j]

    • j - i < 3,则 dp[i][j] = true
    • 否则:dp[i][j] = dp[i+1][j-1]
  • 否则:dp[i][j] = false

✅ Go 实现

func longestPalindrome(s string) string {
   
    n := len(s)
    if n < 2 {
   
        return s
    }

    dp := make([][]bool, n)
    for i := range dp {
   
        dp[i] = make([]bool, n)
    }

    maxLen := 1
    start := 0

    for r := 1; r < n; r++ {
   
        for l := 0; l < r; l++ {
   
            if s[l] == s[r] {
   
                if r - l < 3 {
   
                    dp[l][r] = true
                } else {
   
                    dp[l][r] = dp[l+1][r-1]
                }
            }
            if dp[l][r] && r - l + 1 > maxLen {
   
                maxLen = r - l + 1
                start = l
            }
        }
    }

    return s[start:start+maxLen]
}

2️⃣ 最长公共子序列(LeetCode 1143)

📌 题目描述

给定两个字符串 text1text2,返回它们的最长公共子序列的长度。


🧠 解题思路:二维 DP

✅ 状态定义

dp[i][j] 表示 text1[0...i-1]text2[0...j-1] 的最长公共子序列长度。

🔁 状态转移

  • 如果 text1[i-1] == text2[j-1],说明当前字符可加入序列:
    dp[i][j] = dp[i-1][j-1] + 1
  • 否则:
    dp[i][j] = max(dp[i-1][j], dp[i][j-1])

✅ Go 实现

func longestCommonSubsequence(text1 string, text2 string) int {
   
    m, n := len(text1), len(text2)
    dp := make([][]int, m+1)
    for i := range dp {
   
        dp[i] = make([]int, n+1)
    }

    for i := 1; i <= m; i++ {
   
        for j := 1; j <= n; j++ {
   
            if text1[i-1] == text2[j-1] {
   
                dp[i][j] = dp[i-1][j-1] + 1
            } else {
   
                dp[i][j] = max(dp[i-1][j], dp[i][j-1])
            }
        }
    }

    return dp[m][n]
}

func max(a, b int) int {
   
    if a > b {
   
        return a
    }
    return b
}

3️⃣ 编辑距离(LeetCode 72)

📌 题目描述

给你两个单词 word1word2,请返回将 word1 转换成 word2 所使用的最少操作数(插入、删除、替换)。


🧠 解题思路:经典 DP 模板题

✅ 状态定义

dp[i][j] 表示将 word1[0...i-1] 转换为 word2[0...j-1] 所需的最小编辑距离。

🔁 状态转移

  • 如果 word1[i-1] == word2[j-1],则 dp[i][j] = dp[i-1][j-1]
  • 否则取三种操作的最小值加 1:

    • 插入:dp[i][j-1] + 1
    • 删除:dp[i-1][j] + 1
    • 替换:dp[i-1][j-1] + 1

✅ Go 实现

func minDistance(word1 string, word2 string) int {
   
    m, n := len(word1), len(word2)
    dp := make([][]int, m+1)
    for i := range dp {
   
        dp[i] = make([]int, n+1)
    }

    for i := 0; i <= m; i++ {
   
        dp[i][0] = i
    }
    for j := 0; j <= n; j++ {
   
        dp[0][j] = j
    }

    for i := 1; i <= m; i++ {
   
        for j := 1; j <= n; j++ {
   
            if word1[i-1] == word2[j-1] {
   
                dp[i][j] = dp[i-1][j-1]
            } else {
   
                dp[i][j] = min(
                    dp[i-1][j-1], // 替换
                    dp[i][j-1],   // 插入
                    dp[i-1][j],   // 删除
                ) + 1
            }
        }
    }

    return dp[m][n]
}

func min(a, b, c int) int {
   
    if a < b {
   
        if a < c {
   
            return a
        }
        return c
    }
    if b < c {
   
        return b
    }
    return c
}

✅ 总结对比

题目 类型 状态定义 状态转移 重点
5 最长回文子串 判断子串是否回文 dp[i][j] 是不是回文 s[i]==s[j] && dp[i+1][j-1] 需倒序遍历
1143 最长公共子序列 序列匹配 dp[i][j] 表示最长长度 相等加一,否则取较大 不能连续字符
72 编辑距离 转换操作 dp[i][j] 表示最小操作数 插入/删除/替换 三选一 是经典题!

目录
相关文章
|
4月前
|
分布式计算 算法 Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本文讲解了两道经典的图论问题:**岛屿数量(LeetCode 200)** 和 **腐烂的橘子(LeetCode 994)**,分别通过 DFS/BFS 实现。在“岛屿数量”中,利用深度或广度优先搜索遍历二维网格,标记连通陆地并计数;“腐烂的橘子”则采用多源 BFS,模拟腐烂传播过程,计算最短时间。两者均需掌握访问标记技巧,是学习网格搜索算法的绝佳实践。
145 1
|
机器学习/深度学习 JSON 前端开发
RESTful API接口设计规范
近年来移动互联网的发展,前端设备层出不穷(手机、平板、桌面电脑、其他专用设备…),因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信,于是RESTful诞生了,它可以通过一套统一的接口为 Web,iOS和Android提供服务。
3945 1
RESTful API接口设计规范
|
JavaScript Java Linux
Go语言 thrift 入门指南--thrift IDL介绍
Thrift 是一个轻量级、跨语言的 RPC 框架,由 facebook 开发,2007年正式开源,2008 纳入 Apache 软件基金会开源项目。
2027 0
Go语言 thrift 入门指南--thrift IDL介绍
|
3月前
|
缓存 iOS开发 MacOS
uniapp发布快应用失败报错Error: ENOENT: no such file or directory以及hap-chimera-toolkit问题优雅草卓伊凡
uniapp发布快应用失败报错Error: ENOENT: no such file or directory以及hap-chimera-toolkit问题优雅草卓伊凡
366 2
uniapp发布快应用失败报错Error: ENOENT: no such file or directory以及hap-chimera-toolkit问题优雅草卓伊凡
|
4月前
|
机器人 Go
【LeetCode 热题100】网格路径类 DP 系列题:不同路径 & 最小路径和(力扣62 / 64 )(Go语言版)
本篇介绍了网格路径类动态规划问题,涵盖 LeetCode 第 62 题“不同路径”和第 64 题“最小路径和”。通过定义状态 `dp[i][j]` 和转移方程,分别解决路径计数与最小代价问题。两题均支持一维数组优化空间复杂度。总结对比了两题的异同,并延伸至带障碍路径、三角形路径等问题,帮助读者掌握网格 DP 的核心思路:明确状态、写出转移、找准边界。
136 48
|
4月前
|
机器学习/深度学习 JSON 数据格式
快手直播间提取工具,采集直播间弹幕评论点心,最新开源框架【仅供学习参考】
这是一套快手直播弹幕接收与用户信息查询的源码,原本为客户提供定制服务,现分享出来供学习参考。代码基于 `.版本 2` 开发,支持 WebSocket 客户端连接、解析直播间数据、接收弹幕消息及用户操作(如点亮爱心),并展示在线观众数量和用户详细信息。包含多个子程序实现功能模块化,如头像获取、性别判断等。
|
11月前
|
算法 物联网 开发者
In-Context LoRA实现高效多任务图像生成,开启视觉创作新篇章
这篇文章介绍了通义实验室提出的In-Context LoRA,这是一种基于现有文本到图像模型的任务无关性框架,用于实现高质量的多任务图像生成。
1545 11
In-Context LoRA实现高效多任务图像生成,开启视觉创作新篇章
|
11月前
|
消息中间件 存储 Kafka
RocketMQ 工作原理图解,看这篇就够了!
本文详细解析了 RocketMQ 的核心架构、消息领域模型、关键特性和应用场景,帮助深入理解消息中间件的工作原理。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
RocketMQ 工作原理图解,看这篇就够了!
|
11月前
|
前端开发 应用服务中间件 定位技术
Nginx 如何代理转发传递真实 ip 地址?
【10月更文挑战第32天】
2190 5
Nginx 如何代理转发传递真实 ip 地址?
|
12月前
|
存储 安全 数据安全/隐私保护
Maccy: 轻量级剪贴板管理器
【10月更文挑战第10天】
812 4