大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。
题目
394. 字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: 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"
思路
这道题目我用两个栈来存储,stack负责存储字符串,遇到了数字,"[" 或者 "]"进行切割,依次入栈,countStack负责存储每个括号前面的数字,待会儿我们根据这个数字遍历括号中的字符串进行累加。
- 用栈记录每个括号中的内容,经过一轮遍历,遇到了数字我们可以把数字存储到数字栈
countStack中去; - 由于数字可能是多位数,所以我们新增一个变量
isNumber来记录上一个数字是否数字; - 遇到数字的时候,我们需要把前面的前缀全部入栈,放在
stack中,然后记录一下上一位isNumber,这样如果下一位也是数字直接累加即可; - 如果遇到了"[" , 说明数字结束了,把当前值入栈,记得数字存储在
countStack中; - 如果遇到了"]" , 说明括号内容结束,我们直接出栈,从
countStack中取出最后一个元素last,然后重复累加last次当前值即可,记得累加完要把字符串的栈也往前累加一位。
实现
/**
* @param {string} s
* @return {string}
*/
var decodeString = function(s) {
let stack = [], countStack = [];
let prev = "";
let isNumber = false;
for (let i = 0; i < s.length; i++) {
// 如果当前字符是数字, 把前面的存起来
if (!isNaN(Number(s[i]))) {
if (!isNumber) {
stack.push(prev);
prev = s[i];
isNumber = true;
} else {
prev += s[i];
}
} else if (s[i] === "[") {
// 入栈操作,记录数字
countStack.push(Number(prev));
prev = "";
isNumber = false;
} else if (s[i] === "]") {
// 出栈操作,组装单词
let last = countStack.pop();
let cur = prev;
for (let i = 1; i < last; i++) {
prev += cur;
}
// 取出一个括号栈往上走一步,累加
prev = stack.pop() + prev;
isNumber = false;
} else {
prev += s[i];
isNumber = false;
}
}
return prev;
};
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。