题目:字符串解码
- 给定一个经过编码的字符串,返回它解码后的字符串。
- 编码规则为: 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".
来源:力扣(LeetCode)第394题
分析:
两种方法,辅助栈法和递归法,递归法相对思路清晰,比较好做。其实本质两种方法是一样的,因为函数的递归调用其实也是用栈来实现的。
思路:
- 递归法:
- 遍历整个字符串
- 同时要用到stack列表,tmp列表,还有一个表示下标的变量i
- 每次递归之后stack都是该函数的stack,与外面的stack不同
- 每次遍历字符时,tmp都要将里面的值清空
- 遇到字母,压入stack
- 遇到
]
字符,结束函数并将stack返回 - 遇到数字首先判断该数字后是否还有数字,有的话一起加入tmp,然后递归调用函数。
- 辅助栈法:
- 遍历整个字符串
- res表示当前字符串,multi表示当前数字,stack储存答案
- 遇到字母,与res拼接起来
- 遇到数字,放入multi,注意由于两个数字放在一起要变成两位数,以此类推,所以res 写成
res = res * 10 + 当前数字
- 遇到
[
,将res,multi同时入栈,用一个列表或元祖,并行的,不是先后入栈。 - 遇到右括号,栈顶元素出栈,并将栈顶元素的multi与当前字符相乘,然后再与栈顶的res相加
上代码:
递归法:
class Solution: def decodeString(self, s: str) -> str: self.i = 0 return ''.join(self.recursion(s)) def recursion(self, s: str) -> list: stack = [] while self.i < len(s): tmp = [] if s[self.i].isalpha(): stack.append(s[self.i]) elif s[self.i] == ']': return stack elif s[self.i].isdigit(): tmp.append(s[self.i]) while s[self.i + 1].isdigit(): tmp.append(s[self.i + 1]) self.i += 1 self.i += 2 stack += (int(''.join(tmp)) * self.recursion(s)) self.i += 1 return stack
辅助栈法:
class Solution: def decodeString(self, s: str) -> str: stack, res, multi = [], "", 0 for c in s: if c == '[': stack.append([multi, res]) res, multi = "", 0 elif c == ']': cur_multi, last_res = stack.pop() res = last_res + cur_multi * res elif '0' <= c <= '9': multi = multi * 10 + int(c) else: res += c return res
辅助栈法不是我自己写的,可以参考LeetCode上的作者: > https://leetcode-cn.com/problems/decode-string/solution/decode-string-fu-zhu-zhan-fa-di-gui-fa-by-jyd/
复杂度分析:
- 递归法:
- 时间复杂度:O(n) n为字符串长度
- 空间复杂度:O(n)
- 辅助栈法:
- 时间复杂度:O(n) n为字符串长度
- 空间复杂度:O(n)
总结:
- 递归是一种不错的尝试,很多时候递归的时间耗时并不是非常高,而且解题方便。
- 写这种题目前需要理清各种情况时的行为。