给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
测试用例保证输出的长度不会超过 105。
示例 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 <= 30s由小写英文字母、数字和方括号'[]'组成s保证是一个 有效 的输入。s中所有整数的取值范围为[1, 300]
1. 生活案例:多重梦境(盗梦空间)
想象你在经历一场“多重梦境”:
-
规则:当你遇到
[,意味着你进入了下一层梦境。进入之前,你得记住你在现实世界已经说了什么,以及这层梦境要重复几次。 -
过程:
- 你在第一层梦境(外层字符串)。
- 遇到
3[,你赶紧把当前说的话和数字3存进笔记本(栈),然后跳进第二层梦境,开始说新话。 - 遇到
],代表这层梦境结束了。你醒来回到上一层,把你刚才在梦里说的话重复3次,接在笔记本里记录的旧话后面。
2. 代码实现与详细注释
这是你图片中的代码,我为你加上了“梦境视角”的详细中文注释:
JavaScript
/**
* @param {string} s
* @return {string}
*/
var decodeString = function(s) {
let subStr = ''; // 【当前梦境】里正在说的话
let stack = []; // 【笔记本】:记录进入深层梦境前的“状态”
let num = 0; // 【重复次数】:准备要重复几次
for (let char of s) {
if (char >= '0' && char <= '9') {
// 如果是数字,可能不止一位(比如 100),需要累加计算
num = num * 10 + Number(char);
} else if (char === '[') {
// 【进入新梦境】:
// 1. 把“之前梦境说的话”和“本次要重复的次数”打包存进笔记本
stack.push([subStr, num]);
// 2. 清空状态,开始记录新梦境里的台词和次数
subStr = '';
num = 0;
} else if (char === ']') {
// 【回到上一层梦境】:
// 1. 从笔记本里翻出进梦前的记录
let [prev, repeatNum] = stack.pop();
// 2. 核心逻辑:上一层的话 + (当前梦境的话 重复 n 次)
subStr = prev + subStr.repeat(repeatNum);
} else {
// 普通字母:直接拼接到当前梦境的台词里
subStr = subStr + char;
}
}
return subStr;
};
3. 核心原理解析
为什么用栈(Stack)?
因为处理嵌套括号遵循**“后进先出”**的原则:最内层的括号(最后一层梦境)必须最先被解开。栈能完美保存每一层“未完成”的现场。
运行轨迹追踪:以 3[a2[c]] 为例
| 步骤 | 字符 | 栈内情况 stack | 当前 subStr | 说明 |
|---|---|---|---|---|
| 1 | 3 | [] | '' | num 变为 3 |
| 2 | [ | [['', 3]] | '' | 存入外层空字符串和 3,清空准备接新词 |
| 3 | a | [['', 3]] | 'a' | 记录当前台词 |
| 4 | 2 | [['', 3]] | 'a' | num 变为 2 |
| 5 | [ | [['', 3], ['a', 2]] | '' | 把当前的 'a' 和 2 存入笔记本,再次清空 |
| 6 | c | [['', 3], ['a', 2]] | 'c' | 记录最内层台词 |
| 7 | ] | [['', 3]] | 'acc' | 出栈 ['a', 2]:'a' + 'c'.repeat(2) |
| 8 | ] | [] | 'accaccacc' | 出栈 ['', 3]:'' + 'acc'.repeat(3) |
复杂度分析
- 时间复杂度:,其中 是解码后字符串的长度。我们需要遍历输入并构建最终结果。
- 空间复杂度:,栈的深度取决于括号嵌套的深度。