给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: 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”
题由于保证了输入一定是有效的,因此我们可以不必考虑括号失配的情形。
由于存在括号嵌套的情况,因此我们不能简单的从左到右匹配输出,而是存在内层括号时,我们应该先算出内层括号中的字符串解码然后再由外层计算,这显然很符合栈 “先进后出”的特性。
对输入字符串s进行遍历,有如下情形:
1 当前字符为数字,那么我们将其累加起来,用做其后【…】字符串出现的次数
2 当前字符为普通字符,我们用一个临时结果集先将其连接
3 当前字符为 “【”,显然此时我们要进入括号内层了,所以进内层前,我们将之前的倍数和之前的 “临时结果集” 先放入栈中,根据栈的特性,我们会先算完内层才会计算外层。然后重置 “临时结果集”为“”, 倍数为0, 因为相当于进入了一个新的子状态。
4 当前字符为 “】”,此时,表示当前某一内层【…】已匹配完,我们向上弹出栈顶(前缀和倍数),将倍数 乘以【…】括号内的内容并加上前缀即可,作为当前的 “临时结果集”,由于进入【 的时候倍数已经置零了,而括号内不允许有数字,因此这个时候出括号的时候倍数还是0,不用管它。
时间复杂度是O(n)
空间复杂度是栈的大小O(n)
class Solution:
def decodeString(self, s: str) -> str:
num = 0
cur = ''
stack = []
for elem in s:
if elem in '0123456789':
num = 10*num + int(elem)
elif elem not in '0123456789[]':
cur += elem
elif elem == '[':
stack.append((num, cur))
num = 0
cur = ''
elif elem == ']':
tempnum, temppre = stack.pop()
cur = temppre + cur*tempnum
return cur
可以看到,栈也可以用递归来代替,递归函数的内容为:
1 我们设置一个i指针,初始指向第一个字符, 然后开始往后遍历。注意递归函数需要将当前字符串置为’’ , 倍数置为0
2 当出现 “【”时,开启下一层递归, 递归返回的是【】里面的内容,和】的位置i,也就是这个时候指针直接跑到】的位置上去了。然后将这个内容呈上倍数并加上前缀得到当前的字符串。将倍数置为0
3 出现 “】”时,向上返回一层,返回当前字符串(也就是这层递归函数处理的【】里面的内容) 和 指针位置( 】的位置 )
空间复杂度O(n)为递归深度
class Solution:
def decodeString(self, s: str) -> str:
return self.decodeStringSub(s, 0)[0]
def decodeStringSub(self, s, i):
num = 0
cur = ''
while i < len(s):
elem = s[i]
if elem in '0123456789':
num = 10*num + int(elem)
elif elem not in '0123456789[]':
cur += elem
elif elem == '[':
tempcur, i = self.decodeStringSub(s, i+1)
cur = cur + tempcur*num
num = 0
elif elem == ']':
return cur, i
i += 1
return cur, i