Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
题目介绍
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: 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 <= 30s由小写英文字母、数字和方括号'[]'组成s保证是一个 有效 的输入。s中所有整数的取值范围为[1, 300]
思路解析
看一下上图的例子,其实每一层的结构都是一样的,对于这种整体结构可以由部分结构来代替的题目,最好的解题方式就是使用递归,并且是只要看最小的一层结构就可以了。
那么以上图中的最小结构 6[ef] 来看一下怎么输出成字符串:
- 首先数字之后就是
[, 而[到与其匹配的]中的内容就是需要我们重复输出的内容,那么这里有两个值我们需要进行记录,一个是循环的次数6,一个是循环的内容ef - 因为数字的范围是
[1, 300],所以当我们遇到第一个数字开始,需要遍历到[为止,并且利用num = num * 10 + +s[i]方法记录完整的数字 - 遇到
[之后,直到遍历到]为止,需要用字符串记录括号中的内容ef - 然后就可以在结果字符串后面拼接
num次ef就可以了
接下来看一下如果是两层的 4[cd6[ef]] 怎么做:
- 首先还是记录循环次数
4 - 这里有两层括号,为了能够匹配到对应的括号,我们利用栈的思想,遇到
[时+1,遇到]时-1 - 记录括号中的内容
cd,然后遇到数字 - 这里就可以开始进入递归了,计算完
6[ef]之后将结果返回到上一层,然后拼接在cd后面 - 当遇到
]且我们记录的值刚好为0时,说明当前的字符串是需要循环一开始记录的4次的 - 循环拼接,然后返回拼接后的字符串即可
更多层的结构同理
解题代码
var decodeString = function(s) {
let str = ''
let i = 0
while(s[i]) {
if (s[i] < '0' || s[i] > '9') {
// 如果不是数字,直接拼字符串
str += s[i]
i++
} else {
let num = 0
// 如果是数字,需要遍历到 [,计算总数
while (s[i] >= '0' && s[i] <= '9') {
num = num * 10 + +s[i++]
}
i++
let l = i, r = i, cnt = 1
// 如果 cnt 不为 0,说明当前层的括号还没有封闭
while(cnt) {
r += 1
if (s[r] === '[') cnt++
if (s[r] === ']') cnt--
}
// 将 [] 中的内容进行递归,拼成字符串
let temp = decodeString(s.substr(l, r - l))
// 将 [] 中的内容循环 num 次拼接在当前的字符串之后
while (num--) str += temp
// r 此时指向 ],需要 +1 指向 ] 后面的元素
i = r + 1
}
}
return str
};