news 2026/1/31 3:55:17

LeetCode 471 编码最短长度的字符串

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 471 编码最短长度的字符串


文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
    • 题解代码分析
      • 为什么用区间 DP
      • 拆分的意义
      • 整体重复的判断逻辑
    • 示例测试及结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

LeetCode 471《编码最短长度的字符串》是一道非常典型但也非常容易被低估的动态规划题
表面上看,它只是把字符串压缩成类似k[substring]的形式;但真正难的地方在于——什么时候该压缩,什么时候不该压缩,以及如何保证整体长度是最短的

这道题和真实业务里很多“字符串优化”“配置压缩”“协议编码”问题的思路是高度相通的。
本文会从直觉思路开始,逐步推到 DP 解法,并给出一个 Swift 的可运行 Demo。

描述

题目要求我们实现一个函数:

给定一个字符串s,对其进行编码,使编码后的字符串长度最短。

编码规则是:

  • 如果一个字符串可以表示为某个子串重复多次
  • 可以写成:k[encoded_string]
  • 其中k是重复次数,encoded_string是被重复的字符串

比如:

  • "aaaaa""5[a]"
  • "ababab""3[ab]"
  • "aabcaabcd""2[aabc]d"

但要注意一个非常重要的点:

如果编码后的字符串不比原字符串短,那就不要编码。

这句话,基本就是这道题 80% 的难点来源。

题解答案

这道题的核心思路可以总结为一句话:

用区间 DP,枚举每一个子串的最优编码结果。

我们用一个二维 DP:

dp[i][j] 表示字符串 s[i...j] 的最短编码结果

对于任意一个子串,我们有两种选择:

  1. 不做压缩,直接用原字符串

  2. 尝试压缩

    • 要么拆分成两段
    • 要么整个子串由某个更小的子串重复构成

最终取长度最短的那个方案。

![](https://i-blog.csdnimg.cn/direct/a0d338fa17054066953ec43bb8f178a1.png

题解代码分析

下面是完整的 Swift 实现代码,可以直接在 LeetCode 或本地 Swift 环境运行

classSolution{funcencode(_s:String)->String{letchars=Array(s)letn=chars.countifn==0{return""}// dp[i][j] 表示 s[i...j] 的最短编码字符串vardp=Array(repeating:Array(repeating:"",count:n),count:n)// 单个字符初始化foriin0..<n{dp[i][i]=String(chars[i])}// 按区间长度递增forlenin2...n{foriin0...n-len{letj=i+len-1letsubstring=String(chars[i...j])dp[i][j]=substring// 默认不编码// 情况一:拆分forkini..<j{letleft=dp[i][k]letright=dp[k+1][j]ifleft.count+right.count<dp[i][j].count{dp[i][j]=left+right}}// 情况二:整体重复letpattern=findRepeatPattern(substring)ifletp=pattern{lettimes=substring.count/p.countletencoded="\(times)[\(p)]"ifencoded.count<dp[i][j].count{dp[i][j]=encoded}}}}returndp[0][n-1]}// 判断字符串是否由某个子串重复构成privatefuncfindRepeatPattern(_s:String)->String?{letchars=Array(s)letn=chars.countforlenin1...n/2{ifn%len!=0{continue}letpattern=Array(chars[0..<len])varmatch=trueforiinstride(from:0,to:n,by:len){ifArray(chars[i..<i+len])!=pattern{match=falsebreak}}ifmatch{returnString(pattern)}}returnnil}}

题解代码分析

这段代码比较长,我们分几块慢慢聊。

为什么用区间 DP

这道题的编码是强子结构问题

  • 子串的最优解,会影响大串的最优解
  • 拆分位置不同,结果完全不同

所以:

  • 一维 DP 根本不够
  • 必须知道每个区间的最优编码

这也是dp[i][j]出现的原因。

拆分的意义

这段代码:

forkini..<j{letleft=dp[i][k]letright=dp[k+1][j]ifleft.count+right.count<dp[i][j].count{dp[i][j]=left+right}}

解决的是这种情况:

"aabcaabcd" = "aabc" + "aabcd"

有些字符串整体无法压缩,但拆开之后能变短。

这在实际场景中非常常见,比如:

  • 模板字符串
  • 日志前缀 + 重复内容
  • 协议字段拼接

整体重复的判断逻辑

这段是整题最容易写错的地方:

letpattern=findRepeatPattern(substring)

它的本质是在问:

这个字符串是不是由一个更短的字符串重复 N 次得到的?

我们做法非常直接:

  1. 枚举所有可能的子串长度len
  2. 判断能不能完整覆盖原字符串
  3. 每一段都严格相等才算成功

注意一个关键点:

即使可以压缩,也要比较长度,不能强行压。

这正是很多人第一次写这道题会踩的坑。

示例测试及结果

我们来跑几个经典用例。

letsolution=Solution()print(solution.encode("aaa"))// 3[a]print(solution.encode("ababab"))// 3[ab]print(solution.encode("aabcaabcd"))// 2[aabc]dprint(solution.encode("abcde"))// abcde

输出结果:

3[a] 3[ab] 2[aabc]d abcde

可以看到:

  • 能压缩的就压
  • 压了不划算的,坚决不动

这正是题目想要的效果。

时间复杂度

时间复杂度主要来自三部分:

  1. 区间 DP:O(n^2)
  2. 每个区间尝试拆分:O(n)
  3. 每次判断重复模式:O(n)

综合下来:

  • 时间复杂度是 O(n³)

虽然看起来不低,但题目本身对n的限制并不大,是完全可以接受的。

空间复杂度

  • 使用了一个n x n的 DP 表
  • 额外的字符串操作是常数级

所以:

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

总结

LeetCode 471 是一道非常适合用来检验你是否真正理解区间 DP 的题

它至少同时考察了三点能力:

  1. 能不能正确建模子问题
  2. 能不能处理“压不压”的决策问题
  3. 能不能在字符串问题里保持足够的耐心和严谨
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/26 21:29:00

6款苹方字体完整指南:让Windows用户也能享受苹果原生字体体验

6款苹方字体完整指南&#xff1a;让Windows用户也能享受苹果原生字体体验 【免费下载链接】PingFangSC PingFangSC字体包文件、苹果平方字体文件&#xff0c;包含ttf和woff2格式 项目地址: https://gitcode.com/gh_mirrors/pi/PingFangSC 还在为网站在不同设备上字体显示…

作者头像 李华
网站建设 2026/1/31 3:48:52

STM32L4系列CubeMX时钟配置完整示例

STM32L4时钟配置实战&#xff1a;从CubeMX到稳定运行的每一步你有没有遇到过这样的情况&#xff1f;代码逻辑没问题&#xff0c;外设初始化也写了&#xff0c;结果IC通信就是没波形&#xff0c;ADC采样乱跳&#xff0c;甚至程序卡在HAL_Init()不动——最后发现&#xff0c;问题…

作者头像 李华
网站建设 2026/1/26 21:21:58

Goldleaf 终极使用指南:从入门到精通 Nintendo Switch 多用途工具

Goldleaf 终极使用指南&#xff1a;从入门到精通 Nintendo Switch 多用途工具 【免费下载链接】Goldleaf &#x1f342; Multipurpose homebrew tool for Nintendo Switch 项目地址: https://gitcode.com/gh_mirrors/go/Goldleaf Goldleaf 是一款专为 Nintendo Switch 设…

作者头像 李华
网站建设 2026/1/25 17:43:18

Cap开源录屏工具:3分钟上手专业级屏幕录制

Cap开源录屏工具&#xff1a;3分钟上手专业级屏幕录制 【免费下载链接】Cap Effortless, instant screen sharing. Open-source and cross-platform. 项目地址: https://gitcode.com/GitHub_Trending/cap1/Cap 还在为制作教学视频、产品演示或技术分享而烦恼吗&#xff…

作者头像 李华
网站建设 2026/1/29 20:04:50

AutoGLM-Phone-9B API设计:移动端接口优化

AutoGLM-Phone-9B API设计&#xff1a;移动端接口优化 随着移动智能设备的普及&#xff0c;用户对本地化、低延迟、高隐私保护的AI服务需求日益增长。在这一背景下&#xff0c;AutoGLM-Phone-9B应运而生——一款专为移动端深度优化的多模态大语言模型&#xff0c;致力于在资源…

作者头像 李华
网站建设 2026/1/28 18:08:57

Kubernetes 核心解析:API Server, Scheduler, Controller Manager

Kubernetes 的控制平面由多个组件组成,其中最核心的三个是: API Server(kube-apiserver) Scheduler(kube-scheduler) Controller Manager(kube-controller-manager) 它们共同构成了 Kubernetes 的“大脑”,负责集群的状态管理、调度与自愈。本文将深入解析这三个核心组…

作者头像 李华