题目
https://leetcode-cn.com/problems/decode-string/
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例:
s = "3[a]2[bc]", 返回 "aaabcbc".
s = "3[a2[c]]", 返回 "accaccacc".
s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".
解题思路(栈)
- 从前向后扫描一次
- 扫描中,遇到数字字符,使用
n = n*10 + int(c)
可更新数字 - 遇到
[
时,用栈存储当前的乘数和字符串前缀,然后将这俩变量清零 - 遇到
]
时,出栈乘数和此前的字符串前缀,据此更新当前字符串前缀 - 这个解法需要注意:
- 字符串前缀和乘数的清零时机
- 入栈的内容,出栈后如何更新字符串前缀
代码(栈)
class Solution:
def decodeString(self, s: str):
stack = []
n, res = 0, ''
for c in s:
if c.isdigit():
# - update n
n = n*10 + int(c)
elif c.isalpha():
# - update word
res += c
elif c == '[':
# - use stack to keep current n and res
stack.append([n, res])
n, res = 0, ''
elif c == ']':
# - last n and res
m, t = stack.pop()
# - update res
res = t + m*res
else:
pass
return res
解题思路(递归)
- 递归的思路是扫描到
[
就将递归处理此后的字符串,直到遇到]
结束 - 因为需要跳过处理过的子串,所以需要将结尾下标也作为返回值传出
- 需要注意的是,获取到递归的返回值后,更新了字符串前缀,别忘了乘数重置为0
代码(递归)
class Solution:
def decodeString(self, s: str):
def dfs(i):
res, n = '', 0
while i < len(s):
c = s[i]
if c.isdigit():
n = n*10 + int(c)
elif c.isalpha():
res += c
elif c == '[':
r, i = dfs(i+1)
res += r * n
n = 0
elif c == ']':
return res, i
else:
pass
i += 1
return res, i
return dfs(0)[0]
总结
其实DFS的递归,也是使用栈来存储临时变量的,二者没啥本质区别