携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第27天,点击查看活动详情
题目描述
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k,例如不会出现像 3a 或 2[4] 的输入。
示例 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]
解题思路
从题目可以知道,字符串是以 k[encoded_string] 的形式组成的,意思是将 encoded_string 重复 k 次。
我们看看示例一,3[a]2[bc],将 a.repeat(3) + bc.repeat(2),最终的结果是 aaabcbc。这么一看很简单嘛,只要记录 [ 左边的 数字(不一定是个位数),和 [] 里的 字符串。
于是我一开始是使用两个变量,num 拼接数字,res 拼接字符串,如果遇到 ] 符号就将 res 重复 num 次后重新赋值给 res,直到循环结束。
这样真的可以吗?
如果是没有 嵌套 的括号,那么这样的毛闷台的,但是 middle 的题目怎么会让你笑着睡觉呢?碰到 3[a2[c]] 这样的直接就 gg 了。
所以重中之重还是要解决嵌套的问题。
还是 3[a2[c]] 这个例子,明显的,我们需要将 2 * c 的结果用 a 拼接后再乘 3。
我们知道 3[xxxx] 也就是 xxxx.repeat(3),那么我们碰到数字就需要记录这个数字了,别急,再看看 a2[xxx] 这部分,它表示 a + xxx.repeat(2),所以我们在 [ 前可能碰到 数字 | 字母+数字 这两种组合。那么 3[a2[c]] 这种嵌套形式,我们可以 把每一层嵌套看成每一层栈,我们将每层的重复次数和当前应重复的字符串都存入同一层栈中。
比如这个例子:将 ['', 3] 存入栈中,将 ['a', 2] 存入栈中, 将 ['c', 0] 存入栈中。由于栈是后入先出的,所以我们从栈顶开始,结果字符串 res = '',res = 'c' + res.repeat(0) === 'c',然后出栈,继续将栈顶:res = 'a' + res.repeat(2) === 'acc',出栈,继续将栈顶:res = '' + res.repeat(3) === accaccacc,出栈,栈为空,结束。
题解
/**
* @param {string} s
* @return {string}
*/
var decodeString = function(s) {
const stack = [];
let res = '', num = 0;
for(let w of s) {
if(isDigit(w)) {
num = +w + num * 10;
} else if(isWord(w)) {
res += w;
} else if(w === '[') {
stack.push([res, num]);
res = '';
num = 0;
} else if(w === ']') {
const [word, cnt] = stack.pop();
res = word + res.repeat(cnt);
}
}
return res;
};
const isDigit = v => v >= '0' && v <= '9';
const isWord = v => v >= 'a' && v <= 'z';