1. 题目
为了提升数据传输的效率,会对传输的报文进行压缩处理。输入一个压缩后的报文,请返回它解压后的原始报文。
- 压缩规则:n[str],表示方括号内部的 str 正好重复 n 次。注意 n 为正整数(0 < n <= 100),str只包含小写英文字母,不考虑异常情况。
- 输入描述:
- 输入压缩后的报文:
- 不考虑无效的输入,报文没有额外的空格,方括号总是符合格式要求的;
- 原始报文不包含数字,所有的数字只表示重复的次数 n ,例如不会出现像 5b 或 3[8] 的输入;
- 输出描述:
- 注:
示例1
输入
3[k]2[mn]
输出
kkkmnmn
说明
k 重复3次,mn 重复2次,最终得到 kkkmnmn
示例2
输入
3[m2[c]]
输出
mccmccmcc
说明
m2[c] 解压缩后为 mcc,重复三次为 mccmccmcc”
2. 解题思路
-
对于字符串解析问题,我们很容易想到使用栈来解决。将字符串中除 ]
之外的字符推入栈中,之后当遇到 ]
时,我们让栈中的数字或字母进行出栈,然后进行一些操作。
-
那么如何判断什么时候停止出栈呢?毫无疑问,我们需要加一个状态判断,如果满足这个状态,我们就让栈弹出的循环停下来。而这个状态,其实已经存在于字符串中了,那就是 [
字符。因此我们让 [
字符也一起入栈,等我们栈顶弹出时发现遇到了第一个 [
时,就立即停止栈的弹出,然后继续将报文后续的字符入栈,这就是整个解析的大致过程。
-
但是问题也随之而来,当我们栈弹出时,我们怎么判断弹出的是一个完整的序列呢?就拿 3[m2[c]]
这串报文来说,我们弹出 2
的时候怎么知道已经解析完了数字部分呢?它也可能是一个两位数或者更多位的数字,因此我们在这里要进行一系列判断,然后还要进行其他操作,比如暂存字符串、数学运算。有没有更好的方法规避这个问题?有的,如果我们提前将报文转成数组,然后让英文字母和数字单独连接在一起,之后我们就不需要进行额外的判断和操作了。具体来说:
// 对于像下面这种报文
let str = '34[m22[cn]]';
// 我们将其转为数组后,将数字和字母分别串联在一起后就变成了下面这样的形式:
let arr = ['34','[', 'm', '22', '[', 'cn', ']', ']'];
经过这样的转变,我们就无需对数字或者字母的完整性做任何判断,避免了复杂的逻辑。
-
解决了栈中字符的完整性判断问题&