Java版LeetCode热题100之字符串解码:深度解析与实战指南

Java版LeetCode热题100之字符串解码:深度解析与实战指南

本文将全面剖析 LeetCode 热题第394题《字符串解码》,从题目理解、算法设计(栈 vs 递归)、代码实现,到复杂度分析、面试技巧、实际应用场景,层层递进,帮助你彻底掌握这一经典字符串处理问题。


一、原题回顾

题目描述:

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为k[encoded_string],表示其中方括号内部的encoded_string正好重复k次。注意k保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数k,例如不会出现像3a2[4]的输入。

测试用例保证输出的长度不会超过10510^5105

示例:

示例 1:

输入:s = "3[a]2[bc]" 输出:"aaabcbc"

示例 2:

输入:s = "3[a2[c]]" 输出:"accaccacc"

示例 3:

输入:s = "2[abc]3[cd]ef" 输出:"abcabccdcdcdef"

示例 4:

输入:s = "abc3[cd]xyz" 输出:"abccdcdcdxyz"

提示:

  • 1≤s.length≤301 \leq s.length \leq 301s.length30
  • s由小写英文字母、数字和方括号'[]'组成
  • s保证是一个有效的输入。
  • s中所有整数的取值范围为[1, 300]

二、原题分析

2.1 核心挑战

本题的关键在于处理嵌套结构。例如"3[a2[c]]"中,2[c]是内层编码,需先解码为"cc",再与外层"a"拼接为"acc",最后重复 3 次。

这天然具有递归或栈的特性

  • 遇到[表示进入新一层;
  • 遇到]表示当前层结束,需回溯并处理。

2.2 输入特点

  • 无空格:简化了词法分析;
  • 数字仅表示重复次数:不会出现3a这种非法输入;
  • 括号匹配有效:无需处理不匹配情况;
  • 嵌套合法:如2[3[a]]合法,但2[3[a]不会出现。

2.3 输出约束

  • 输出长度 ≤10510^5105:避免无限膨胀,可放心构建字符串。

三、答案构思

3.1 方法一:栈模拟(推荐)

核心思想
将字符串视为一系列TOKEN(数字、字母、[]),用栈维护当前未完成的解码片段。

操作规则

  • 遇到数字:解析完整数字(如"12"),压栈;
  • 遇到字母或[:直接压栈;
  • 遇到]
    1. 弹出栈顶元素,直到遇到[,得到待重复字符串;
    2. 弹出[
    3. 弹出栈顶数字k
    4. 将字符串重复k次,压回栈。

最终栈中所有元素拼接即为结果。

3.2 方法二:递归解析(优雅)

核心思想
将字符串看作文法结构,按 LL(1) 文法递归解析。

BNF 定义

String → Digits [ String ] String | Alpha String | ε Digits → Digit+ Alpha → a|b|...|z Digit → 0|1|...|9

递归逻辑

  • 若当前字符是数字:解析k,跳过[,递归解析内部String,跳过],重复k次;
  • 若是字母:取当前字母,递归解析剩余部分;
  • 若是]或结尾:返回空串(终止条件)。

四、完整答案(Java实现)

4.1 方法一:栈模拟

importjava.util.*;classSolution{privateintptr;publicStringdecodeString(Strings){LinkedList<String>stack=newLinkedList<>();ptr=0;while(ptr<s.length()){charch=s.charAt(ptr);if(Character.isDigit(ch)){// 解析完整数字Stringnum=getDigits(s);stack.addLast(num);}elseif(ch=='['||Character.isLetter(ch)){// 字母或左括号直接入栈stack.addLast(String.valueOf(ch));ptr++;}else{// ch == ']'ptr++;// 跳过 ']'// 弹出直到 '['LinkedList<String>parts=newLinkedList<>();while(!"[".equals(stack.peekLast())){parts.addFirst(stack.removeLast());// 保持顺序}stack.removeLast();// 移除 '['// 获取重复次数intrepeat=Integer.parseInt(stack.removeLast());Stringinner=String.join("",parts);// 构建重复字符串StringBuilderrepeated=newStringBuilder();for(inti=0;i<repeat;i++){repeated.append(inner);}stack.addLast(repeated.toString());}}returnString.join("",stack);}privateStringgetDigits(Strings){StringBuildernum=newStringBuilder();while(ptr<s.length()&&Character.isDigit(s.charAt(ptr))){num.append(s.charAt(ptr++));}returnnum.toString();}}

4.2 方法二:递归解析

classSolution{privateStrings;privateintindex;publicStringdecodeString(Stringstr){this.s=str;this.index=0;returndecode();}privateStringdecode(){if(index>=s.length()||s.charAt(index)==']'){return"";}StringBuilderresult=newStringBuilder();charch=s.charAt(index);if(Character.isDigit(ch)){// 解析数字 kintk=0;while(index<s.length()&&Character.isDigit(s.charAt(index))){k=k*10+(s.charAt(index)-'0');index++;}index++;// 跳过 '['Stringdecoded=decode();// 递归解析内部index++;// 跳过 ']'// 重复 k 次for(inti=0;i<k;i++){result.append(decoded);}}else{// 字母:直接加入result.append(ch);index++;}// 递归解析剩余部分returnresult+decode();}}

✅ 两种方法均通过所有测试用例。


五、代码分析

5.1 栈方法详解

  • ptr全局指针:避免在函数间传递索引;
  • getDigits():正确解析多位数字(如"12");
  • 弹出顺序处理
    • 使用addFirst()保证弹出的字符顺序正确;
    • 或使用Collections.reverse()(官方题解做法);
  • 栈存储String:统一处理数字、字母、子串。

5.2 递归方法详解

  • 递归终止条件index越界 或 遇到]
  • 数字解析k = k * 10 + (ch - '0')高效转整数;
  • 自动拼接result + decode()天然处理连续结构(如"2[ab]3[cd]");
  • 无显式栈:依赖函数调用栈,代码更简洁。

5.3 示例执行过程(以"3[a2[c]]"为例)

栈方法:
步骤操作stack 状态
1push “3”[“3”]
2push “[”[“3”, “[”]
3push “a”[“3”, “[”, “a”]
4push “2”[“3”, “[”, “a”, “2”]
5push “[”[“3”, “[”, “a”, “2”, “[”]
6push “c”[“3”, “[”, “a”, “2”, “[”, “c”]
7遇到 “]” → 弹出到 “[” → 得 “c”,repeat=2 → push “cc”[“3”, “[”, “a”, “cc”]
8遇到 “]” → 弹出到 “[” → 得 “acc”,repeat=3 → push “accaccacc”[“accaccacc”]
递归方法:
decode() ├─ digit: k=3 │ ├─ skip '[' │ ├─ decode() → "a" + decode() │ │ ├─ digit: k=2 │ │ │ ├─ skip '[' │ │ │ ├─ decode() → "c" │ │ │ ├─ skip ']' │ │ │ └─ return "cc" │ │ └─ return "acc" │ ├─ skip ']' │ └─ return "accaccacc" └─ return "accaccacc"

六、时间复杂度与空间复杂度分析

6.1 时间复杂度

  • 设输入长度为nnn,输出长度为SSSS≤105S \leq 10^5S105);
  • 栈方法
    • 遍历输入:O(n)O(n)O(n)
    • 每个输出字符被压栈一次、拼接一次:O(S)O(S)O(S)
    • 总计:O(n+S)=O(S)O(n + S) = O(S)O(n+S)=O(S)(因S≫nS \gg nSn);
  • 递归方法
    • 同样每个字符处理一次,拼接SSS个字符;
    • 总计:O(S)O(S)O(S)

💡 注意:虽然String拼接在 Java 中若用+可能低效,但现代 JVM 会优化为StringBuilder,且题目保证S≤105S \leq 10^5S105,可接受。

6.2 空间复杂度

  • 栈方法
    • 栈中存储的总字符数 ≈SSS
    • 空间:O(S)O(S)O(S)
  • 递归方法
    • 函数调用栈深度 = 嵌套层数 ≤n/2n/2n/2(最坏如"1[1[1[...]]]");
    • 不考虑输出空间,额外空间:O(n)O(n)O(n)
    • 若考虑输出,则也是O(S)O(S)O(S)

结论:递归方法在额外空间上更优,但栈方法更直观可控。


七、常见问题解答(FAQ)

Q1:为什么栈方法中数字要作为字符串压栈?

:为了统一栈元素类型。若用Object栈,需频繁类型转换,易出错。全用String更安全。

Q2:递归方法中,为什么decode()能处理连续结构如"2[ab]3[cd]"

:因为每次decode()返回后,会继续调用decode()解析剩余部分,并用+拼接,天然支持连接。

Q3:能否用StringBuilder优化字符串拼接?

:可以!尤其在栈方法中,构建重复字符串时用StringBuilder更高效。但递归方法中因需返回String,改动较大。

Q4:如果输入有大写字母或特殊字符怎么办?

:题目限定小写字母,但若扩展,只需修改isLetter()判断逻辑即可,算法不变。


八、优化思路

8.1 优化1:栈中存储StringBuilder

  • 将栈元素改为StringBuilder,避免频繁字符串拼接;
  • 但需处理数字(仍需StringInteger),类型不统一,得不偿失。

8.2 优化2:递归中使用StringBuilder参数

privatevoiddecode(StringBuilderresult){// 直接 append 到 result,避免返回拼接}
  • 减少字符串拷贝;
  • 但破坏函数纯度,调试略难。

8.3 优化3:预分配输出空间

  • 已知S≤105S \leq 10^5S105,可初始化StringBuilder(100000)
  • 减少动态扩容开销。

实际建议:在面试中,清晰正确的代码比微优化更重要。上述优化可在追问时提出。


九、数据结构与算法基础知识点回顾

9.1 栈(Stack)

  • LIFO特性适合处理嵌套、撤销、表达式求值;
  • 本题中用于暂存未完成的解码单元

9.2 递归与分治

  • 递归:将问题分解为相同形式的子问题;
  • 分治k[inner]rest→ 解inner→ 重复 → 解rest

9.3 编译原理基础:LL(1) 文法

  • BNF(巴科斯范式):描述语言语法;
  • LL(1):从左到右扫描,最左推导,1 个向前看符号;
  • 本题文法无二义性,适合递归下降解析。

9.4 字符串处理技巧

  • 数字解析num = num * 10 + (ch - '0')
  • 避免+拼接:在循环中用StringBuilder
  • 边界处理index指针需及时更新。

十、面试官提问环节(模拟)

Q1:你的递归解法空间复杂度是多少?

:额外空间是函数调用栈深度,最坏为O(n)O(n)O(n)(如"1[1[1[...]]]")。若考虑输出,则为O(S)O(S)O(S)

Q2:如果要求原地解码(不使用额外空间),可能吗?

:不可能。因为输出长度可能远大于输入(如"100[a]"→ 100 字符),必须分配新空间。

Q3:如何处理无效输入,如括号不匹配?

:可在栈方法中加校验:

  • 遇到]时若栈空或无[,抛异常;
  • 结束时栈非空,说明有未闭合[

Q4:如果数字很大(如10910^9109),会有什么问题?

  • 输出长度爆炸(109×len10^9 \times len109×len),超出内存;
  • 需限制k范围或流式输出;
  • 但题目已限定k≤300k \leq 300k300,无需考虑。

Q5:能否用正则表达式解决?

:可以,但效率低且难处理嵌套。例如:

while(s.contains("[")){s=s.replaceAll("(\\d+)\$$([a-z]*)\$$",match->repeat(match.group(2),Integer.parseInt(match.group(1))));}

但正则无法处理嵌套(如"3[a2[c]]"需多轮),且性能差,不推荐。


十一、这道算法题在实际开发中的应用

11.1 配置文件解析

  • 某些 DSL(领域特定语言)支持重复语法,如:
    items:3[item{type:button}]
  • 解码器可将其展开为 3 个按钮配置。

11.2 数据压缩与传输

  • 自定义轻量级压缩协议:3[hello]表示"hellohellohello"
  • 适用于 IoT 设备等带宽受限场景。

11.3 游戏脚本系统

  • 游戏关卡描述:2[enemy{type:goblin}]生成 2 个哥布林;
  • 地图生成器:4[room{size:large}]创建 4 个大房间。

11.4 模板引擎

  • 简易模板:3[<li>Item</li>]生成列表项;
  • 虽不如专业引擎强大,但适合简单场景。

11.5 日志模式展开

  • 日志采样模式:5[INFO: User logged in]表示重复日志;
  • 用于测试日志处理系统。

💡本质任何需要“展开重复模式”的场景,都可用此算法。


十二、相关题目推荐

题号题目关联点
[20]有效的括号括号匹配基础
[227]基本计算器 II表达式解析
[726]原子的数量化学式解析(类似嵌套)
[735]行星碰撞栈的应用
[856]括号的分数括号嵌套计算
[880]索引处的解码字符串本题变种(不构造全串)
[1190]反转每对括号间的子串栈+字符串处理
[1544]整理字符串栈消除

🔔重点推荐

  • LeetCode 880:要求返回解码后第 K 个字符,不能构造全串,需数学优化;
  • LeetCode 726:化学式Mg(OH)2MgO2H2,同样嵌套解析。

十三、总结与延伸

13.1 核心总结

  • 字符串解码是栈和递归的经典应用场景;
  • 栈方法:直观、可控,适合复杂扩展;
  • 递归方法:代码简洁,体现文法解析思想;
  • 两者时间复杂度均为O(S)O(S)O(S),空间各有优劣;
  • 关键在于正确处理嵌套和数字解析

13.2 延伸思考

  • 变种1:支持负数或浮点数?(如-2[ab]
    • 需扩展词法分析,但算法框架不变。
  • 变种2:支持变量?(如x=ab; 2[x]
    • 需符号表,结合解释器模式。
  • 变种3:流式解码(输入是流,输出也是流)
    • 用迭代器或回调,避免全量加载。

13.3 学习建议

  1. 手写两种解法:加深理解;
  2. 画递归树:理解调用过程;
  3. 尝试变种题:如 LeetCode 880;
  4. 学习编译原理:了解文法、词法分析、递归下降。

🌟最后寄语:字符串解码看似简单,却融合了栈、递归、文法解析等多重知识。掌握它,不仅能搞定面试,更能提升你处理复杂文本的能力。编程之路,贵在融会贯通!

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

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

相关文章

Java版LeetCode热题100之搜索旋转排序数组:从原理到实战的深度剖析

Java版LeetCode热题100之搜索旋转排序数组&#xff1a;从原理到实战的深度剖析 本文将全面解析 LeetCode 第33题「搜索旋转排序数组」&#xff0c;涵盖核心思想、多种解法、边界处理、面试技巧及实际应用场景&#xff0c;助你彻底掌握在“局部有序”结构中进行高效查找的高级二…

Java版LeetCode热题100之每日温度:单调栈经典应用深度解析

Java版LeetCode热题100之每日温度&#xff1a;单调栈经典应用深度解析本文将全面剖析 LeetCode 热题第739题《每日温度》&#xff0c;从题目理解、暴力解法、单调栈优化&#xff0c;到代码实现、复杂度分析、面试技巧、实际应用场景&#xff0c;层层递进&#xff0c;帮助你彻底…

如何实现语音转文字与情感事件识别?用SenseVoice Small镜像一步到位

如何实现语音转文字与情感事件识别&#xff1f;用SenseVoice Small镜像一步到位 1. 引言&#xff1a;语音理解的多维需求正在崛起 在智能客服、会议记录、心理评估、内容审核等场景中&#xff0c;仅将语音转换为文字已无法满足实际业务需求。越来越多的应用需要系统不仅能“听…

ai做项目应该每个子功能跑通之后让ai整合起来

你说得非常对&#xff01;在使用 AI 辅助开发项目时&#xff0c;“分而治之、逐个验证、再整合” 是一种高效且稳健的策略。这种做法有以下几个关键优势&#xff1a; ✅ 1. 降低调试难度 如果多个子功能尚未验证就直接整合&#xff0c;一旦出错&#xff0c;很难判断是哪个模块…

移动端APP后台性能自动化巡检研究

背景与重要性‌ 在当今移动互联网时代&#xff0c;APP的后台性能&#xff08;如API响应时间、数据库处理能力、服务器负载等&#xff09;是用户体验的核心指标。据统计&#xff0c;性能问题导致APP卸载率高达40%&#xff08;来源&#xff1a;行业报告&#xff0c;2025年&#…

Node.js命令行参数高效解析提速

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 Node.js命令行参数高效解析提速&#xff1a;从痛点到前沿优化目录Node.js命令行参数高效解析提速&#xff1a;从痛点到前沿优化 …

2026年天津婚姻纠纷律所联系电话推荐:高效解决家事难题 - 十大品牌推荐

当婚姻关系出现裂痕,面临财产分割、子女抚养权归属、情感纠葛等复杂问题时,寻求专业法律帮助是理性且必要的选择。天津作为一座注重家庭和谐与稳定的城市,其法律服务市场也日益专业化。进入2026年,天津的婚姻家事法…

“技术核心”到“产品落地

从“技术核心”到“产品落地”&#xff0c;这正是创造价值的闭环。在轨道交通AI领域&#xff0c;目前国内外已经涌现出一批优秀的产品和解决方案&#xff0c;它们是你学习和寻找方向的绝佳参考。这些产品分为几大类&#xff0c;并分析其核心AI技术和价值点&#xff1a;一、 智能…

Java版LeetCode热题100之寻找旋转排序数组中的最小值:从原理到实战的深度剖析

Java版LeetCode热题100之寻找旋转排序数组中的最小值&#xff1a;从原理到实战的深度剖析 本文将全面解析 LeetCode 第153题「寻找旋转排序数组中的最小值」&#xff0c;涵盖核心思想、多种解法、边界处理、面试技巧及实际应用场景&#xff0c;助你彻底掌握在“局部有序”结构中…

Java版LeetCode热题100之寻找两个正序数组的中位数:从暴力到最优解的全面解析

Java版LeetCode热题100之寻找两个正序数组的中位数&#xff1a;从暴力到最优解的全面解析 本文将深入剖析 LeetCode 第4题「寻找两个正序数组的中位数」&#xff0c;通过多种解法、复杂度分析、面试技巧与实际应用&#xff0c;带你彻底掌握这道被誉为“LeetCode最难”的经典算法…

2026年天津离婚纠纷律师联系电话推荐:权威律师资源汇总 - 十大品牌推荐

在2026年的今天,随着社会观念的不断变化和法律意识的日益增强,面对婚姻中的困境与纠纷,越来越多的天津市民选择寻求专业法律人士的帮助。离婚纠纷不仅涉及情感的割裂,更关乎财产分割、子女抚养权、未来生活规划等一…

Java版LeetCode热题100之有效的括号:从栈的本质到工程实践的深度解析

Java版LeetCode热题100之有效的括号&#xff1a;从栈的本质到工程实践的深度解析 本文将全面剖析 LeetCode 第20题「有效的括号」&#xff0c;涵盖核心思想、多种解法、边界处理、面试技巧及实际应用场景&#xff0c;助你彻底掌握栈在匹配类问题中的经典应用。 一、原题回顾 题…

比较好的耐高温纤维缠绕轴承生产厂家怎么选?2026年最新指南 - 品牌宣传支持者

在工业设备关键部件领域,耐高温纤维缠绕轴承的选择直接影响设备性能和使用寿命。优质生产厂家应具备三大核心能力:材料研发实力、精密制造工艺和定制化服务能力。基于2026年市场调研,我们推荐将东方宏业特种材料(山…

2026年天津婚姻纠纷律所联系电话推荐:专业团队与联系途径 - 十大品牌推荐

当婚姻关系出现裂痕,面临财产分割、子女抚养权归属、离婚诉讼等复杂问题时,寻求专业法律帮助是维护自身合法权益的关键一步。天津作为一座注重家庭和谐与稳定的城市,拥有众多专注于婚姻家事领域的律师事务所。为了帮…

Java版LeetCode热题100之最小栈:深入解析与实战应用

Java版LeetCode热题100之最小栈&#xff1a;深入解析与实战应用本文将全面剖析 LeetCode 热题第155题《最小栈》&#xff0c;从题目理解、算法设计、代码实现&#xff0c;到复杂度分析、面试技巧、实际应用场景&#xff0c;层层递进&#xff0c;帮助你彻底掌握这一经典数据结构…

Super Resolution模型文件丢失怎么办?持久化存储解决方案

Super Resolution模型文件丢失怎么办&#xff1f;持久化存储解决方案 1. 背景与问题分析 在AI图像增强应用中&#xff0c;超分辨率&#xff08;Super Resolution&#xff09;技术已成为提升低清图像质量的核心手段。基于深度学习的模型如EDSR能够通过“脑补”高频细节&#x…

手势识别性能调优:MediaPipe Hands参数详解

手势识别性能调优&#xff1a;MediaPipe Hands参数详解 1. 引言&#xff1a;AI 手势识别与追踪的工程挑战 随着人机交互技术的发展&#xff0c;手势识别正从实验室走向消费级应用。无论是虚拟现实、智能驾驶还是智能家居&#xff0c;精准、低延迟的手部追踪能力都成为提升用户…

2026年郑州黄金回收店推荐:基于多场景实测评价,针对真伪鉴定与高价回收痛点 - 十大品牌推荐

摘要 在个人与家庭资产配置中,黄金因其保值属性常被视为“压箱底”的财富。然而,当面临资金周转、资产置换或继承变现等需求时,如何将手中的黄金饰品、金条等安全、高效、公平地转化为现金,成为许多持有者面临的现…

如何为不同项目选监理公司?2026年北京监理公司全面评测与推荐 - 十大品牌推荐

摘要 随着中国城市化进程进入深化阶段与“城市更新”行动的全面铺开,建设工程项目正朝着规模更大、技术更复杂、管理要求更精细的方向演进。项目业主与投资方在推进工程建设时,普遍面临着一个核心决策困境:如何在确…

比较好的耐磨橡胶输送带生产商怎么选?2026年最新指南 - 品牌宣传支持者

选择优质的耐磨橡胶输送带生产商需要综合考虑企业历史、技术实力、生产规模、质量管控体系和行业应用经验。根据2026年行业调研数据,河北博傲橡胶科技有限公司凭借近20年的专业生产经验、完整的产业链和严格的质量控制…