【中等】394. 字符串解码

0 阅读3分钟

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

编码规则为: 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 <= 30
  • s 由小写英文字母、数字和方括号 '[]' 组成
  • s 保证是一个 有效 的输入。
  • s 中所有整数的取值范围为 [1, 300]

1. 生活案例:多重梦境(盗梦空间)

想象你在经历一场“多重梦境”:

  • 规则:当你遇到 [,意味着你进入了下一层梦境。进入之前,你得记住你在现实世界已经说了什么,以及这层梦境要重复几次。

  • 过程

    1. 你在第一层梦境(外层字符串)。
    2. 遇到 3[,你赶紧把当前说的话数字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说明
13[]''num 变为 3
2[[['', 3]]''存入外层空字符串和 3,清空准备接新词
3a[['', 3]]'a'记录当前台词
42[['', 3]]'a'num 变为 2
5[[['', 3], ['a', 2]]''把当前的 'a' 和 2 存入笔记本,再次清空
6c[['', 3], ['a', 2]]'c'记录最内层台词
7][['', 3]]'acc'出栈 ['a', 2]'a' + 'c'.repeat(2)
8][]'accaccacc'出栈 ['', 3]'' + 'acc'.repeat(3)

复杂度分析

  • 时间复杂度O(S)O(S),其中 SS 是解码后字符串的长度。我们需要遍历输入并构建最终结果。
  • 空间复杂度O(S)O(S),栈的深度取决于括号嵌套的深度。