题目描述

题解一(双栈操作)
思路

模拟过程(abc3[cd]xyz)

代码
java
class Solution {
public String decodeString(String s) {
// 用于存放重复次数的栈
Stack<Integer> countStack = new Stack<>();
// 用于存放字符串前缀的栈
Stack<StringBuilder> stringStack = new Stack<>();
// 记录当前的字符串
StringBuilder currentString = new StringBuilder();
// 记录当前的数字(重复次数)
int k = 0;
for (char ch : s.toCharArray()) {
if (Character.isDigit(ch)) {
// 处理多位数字的情况,例如 "12[a]"
k = k * 10 + (ch - '0');
} else if (ch == '[') {
// 遇到 '[',将当前累计的数字和字符串入栈保存
countStack.push(k);
stringStack.push(currentString);
// 重置 k 和 currentString,准备记录括号内的内容
currentString = new StringBuilder();
//===================================================================================================
//问题1:这里重置currentString能不能用currentString.setLength(0),因为频繁 new 对象可能带来的性能和内存开销
//===================================================================================================
k = 0;
} else if (ch == ']') {
// 遇到 ']',开始解码当前括号内的字符串
StringBuilder decodedString = stringStack.pop();
int currentK = countStack.pop();
// 将当前字符串重复 currentK 次,拼接到之前弹出的前缀字符串后面
for (int i = 0; i < currentK; i++) {
decodedString.append(currentString);
}
// 更新 currentString 为拼接后的结果
currentString = decodedString;
} else {
// 遇到普通字母,直接追加到当前字符串后面
currentString.append(ch);
}
}
return currentString.toString();
}
}
问题1:这里重置currentString能不能用currentString.setLength(0),因为频繁 new 对象可能带来的性能和内存开销

复杂度分析
- 时间复杂度:O(N)O(N)O(N),其中 NNN 是解码后字符串的长度。虽然代码中有嵌套的 for 循环,但实际上我们是对解码后的每一段字符进行了构建操作,总共构建出的字符数量与最终结果长度一致
- 空间复杂度:O(S)O(S)O(S),其中 SSS 是输入字符串的长度。在最坏的情况下(比如 2[2[2[a]]] 这种连续嵌套),栈的最大深度会与字符串中 [ 的数量成正比,即线性级别的额外空间
题解二(递归)
思路

代码
java
class Solution {
// 全局指针,记录当前遍历到字符串的哪个位置
private int ptr = 0;
public String decodeString(String s) {
StringBuilder currentString = new StringBuilder();
int k = 0;
// 当指针没有越界时继续解析
while (ptr < s.length()) {
char ch = s.charAt(ptr);
if (Character.isDigit(ch)) {
// 解析数字
k = k * 10 + (ch - '0');
ptr++;
} else if (ch == '[') {
// 遇到 '[',跳过它,并进入下一层递归解析括号内的字符串
ptr++;
String subString = decodeString(s);
// 将内层递归返回的字符串重复 k 次,拼接到当前层
for (int i = 0; i < k; i++) {
currentString.append(subString);
}
// 重置 k,为当前层的下一个可能的重复段做准备
k = 0;
} else if (ch == ']') {
// 遇到 ']',说明当前层级的括号解析完毕
// 跳过 ']',并把当前层构建好的字符串返回给上一层
ptr++;
return currentString.toString();
} else {
// 普通字母,直接追加
currentString.append(ch);
ptr++;
}
}
// 最终返回最外层解析的结果
return currentString.toString();
}
}
复杂度分析
- 时间复杂度:O(N)O(N)O(N),其中 NNN 是解码后字符串的长度。本质上还是对解码后的每一个字符都进行了处理和追加操作
- 空间复杂度:O(S)O(S)O(S),其中 SSS 是输入字符串的长度。这里的空间开销主要来自于递归调用栈的深度。在极端嵌套的情况下(如 3[a2[b1[c]]]),递归深度与左括号 [ 的数量成正比