LeetCode 394. 字符串解码详解:Java栈实现与逐行解析
文章目录
- 1. 问题描述
- 2. 解决思路
- 核心问题
- 栈的应用
- 遍历逻辑
- 3. 完整代码实现
- 4. 关键代码解析
- 处理右括号 `]`
- 处理嵌套的示例
- 5. 复杂度分析
- 6. 总结
1. 问题描述
给定一个经过编码的字符串,要求将其解码为原始字符串。编码规则为 k[encoded_string]
,表示方括号内的 encoded_string
重复 k
次。其中 k
为正整数,且输入的字符串保证合法。编码字符串中可能存在多层嵌套括号,例如 3[a2[c]]
解码后为 accaccacc
。
示例:
- 输入:
s = "3[a2[c]]"
- 输出:
"accaccacc"
2. 解决思路
核心问题
处理嵌套括号和重复次数的叠加关系,需确保内层括号的字符串先解码,再与外层结果拼接。
栈的应用
- 双栈结构:使用两个栈分别存储重复次数和字符串片段。
- 次数栈 (
countStack
):存储遇到的重复次数k
。 - 字符串栈 (
stringStack
):存储遇到左括号[
前的字符串片段。
- 次数栈 (
- 当前状态维护:
num
:累积当前数字(可能为多位数)。res
:记录当前正在处理的字符串。
遍历逻辑
- 遇到数字:累积到
num
。 - 遇到左括号
[
:将num
和res
压入栈,并重置num
和res
。 - 遇到右括号
]
:弹出栈顶元素,拼接重复后的字符串。 - 遇到字母:直接追加到当前字符串。
3. 完整代码实现
import java.util.Stack;class Solution {public String decodeString(String s) {StringBuilder res = new StringBuilder(); // 当前处理的字符串Stack<Integer> countStack = new Stack<>(); // 存储重复次数k的栈Stack<StringBuilder> stringStack = new Stack<>(); // 存储外层字符串的栈int num = 0; // 当前累积的数字for (char c : s.toCharArray()) {if (Character.isDigit(c)) {// 处理多位数字,如 "100" 中的 '1','0','0'num = num * 10 + (c - '0');} else if (c == '[') {// 压栈:保存当前状态(重复次数和字符串)countStack.push(num);stringStack.push(res);// 重置状态,准备处理括号内的内容res = new StringBuilder();num = 0;} else if (c == ']') {// 弹出栈顶元素,拼接重复后的字符串int k = countStack.pop(); // 重复次数StringBuilder prev = stringStack.pop(); // 外层字符串片段String temp = res.toString(); // 当前括号内的结果for (int i = 0; i < k; i++) {prev.append(temp); // 重复k次并拼接}res = prev; // 更新当前字符串为拼接后的结果} else {// 字母字符直接追加res.append(c);}}return res.toString();}
}
4. 关键代码解析
处理右括号 ]
int k = countStack.pop(); // 弹出最近的重复次数k
StringBuilder prev = stringStack.pop(); // 弹出外层字符串片段
String temp = res.toString(); // 当前括号内的字符串for (int i = 0; i < k; i++) { prev.append(temp); // 将temp重复k次拼接到prev
}res = prev; // 更新当前字符串为拼接后的结果
- 弹出栈顶元素:
k
是当前括号的重复次数,prev
是进入当前括号前的外层字符串。 - 拼接逻辑:将当前括号内的字符串
temp
重复k
次,拼接到prev
后,更新res
。
处理嵌套的示例
以 3[a2[c]]
为例:
- 初始状态:
res = ""
,栈为空。 - 遇到
3[
:压栈countStack = [3]
,stringStack = [""]
,重置res = ""
。 - 处理
a
:res = "a"
。 - 遇到
2[
:压栈countStack = [3, 2]
,stringStack = ["", "a"]
,重置res = ""
。 - 处理
c
:res = "c"
。 - 遇到
]
:弹出k=2
和prev="a"
,拼接后res = "acc"
。 - 再次遇到
]
:弹出k=3
和prev=""
,拼接后res = "accaccacc"
。
5. 复杂度分析
- 时间复杂度:O(n),其中 n 是解码后的字符串长度。每个字符最多被处理一次。
- 空间复杂度:O(m),m 是输入字符串中括号的嵌套层数,栈的深度与嵌套层数相关。
6. 总结
通过栈结构,可以高效处理嵌套括号问题,每次遇到左括号时保存当前状态,遇到右括号时恢复状态并拼接结果。该方法逻辑清晰,能够处理任意层数的嵌套结构,是解决此类编码字符串问题的经典方案。