983 words
5 minutes
字符串解码

题目描述#

给定一个经过编码的字符串,返回它的解码字符串。

编码规则#

编码规则为:k[encoded_string],表示方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

假设和约束#

  • 输入字符串总是有效的。
  • 输入字符串中没有额外的空格。
  • 输入的方括号总是符合格式要求的(即括号是平衡的)。
  • 原始数据不包含数字,所有的数字只表示重复的次数 k。例如,不会出现像 3a2[4] 这样的输入。
  • 解码后的字符串最大长度保证不超过 10^5

示例#

示例 1#

输入: s = "3[a]2[bc]"

输出: "aaabcbc"

解释: 3[a] 解码为 aaa2[bc] 解码为 bcbc。将它们连接起来得到 aaabcbc

示例 2#

输入: s = "3[a2[c]]"

输出: "accaccacc"

解释: 这个例子展示了嵌套编码。首先,内层括号中的 2[c] 解码为 cc。所以 a2[c] 变成 acc。然后,3[acc] 解码为 accaccacc

示例 3#

输入: s = "2[abc]3[cd]ef"

输出: "abcabccdcdcdef"

解释: 2[abc] 解码为 abcabc3[cd] 解码为 cdcdcdef 保持不变。将这些部分连接起来得到 abcabccdcdcdef

示例 4#

输入: s = "abc3[cd]xyz"

输出: "abccdcdcdxyz"

解释: abc 保持不变。3[cd] 解码为 cdcdcdxyz 保持不变。将这些部分连接起来得到 abccdcdcdxyz

提示#

  • 1 <= s.length <= 30
  • s 由小写英文字母、数字(0-9)和方括号 '['']' 组成
  • s 保证是一个有效的输入
  • s 中所有整数的取值范围为 [1, 300]

解题思路#

根据提示中的内容,可以知道我们接收到的输入只有四种情况:

  1. 英文字母
  2. 数字
  3. 左方括号 [
  4. 右方括号 ]

核心思想#

这是一个典型的应用问题。由于编码字符串可能包含嵌套结构(如示例 2 中的 3[a2[c]]),我们需要使用栈来保存外层的信息,以便在处理完内层后能够正确恢复。

算法步骤#

  1. 使用栈存储上下文:栈中存储 (重复次数, 前缀字符串) 的元组,用于保存遇到 [ 之前的状态。

  2. 遍历字符串,根据不同字符类型进行处理

    • 数字字符:连续读取所有数字字符,转换为整数,作为后续 [...] 的重复次数。
    • 左方括号 [:遇到 [ 时,说明即将开始一个新的编码块。此时将当前的重复次数和已构建的字符串压入栈中保存,然后重置当前状态(重复次数设为 0,字符串清空),准备处理内层内容。
    • 右方括号 ]:遇到 ] 时,说明当前编码块结束。从栈中弹出之前保存的状态 (pre_num, pre_str),将当前字符串重复 pre_num 次,然后拼接到 pre_str 后面,作为新的当前字符串。
    • 英文字母:直接添加到当前字符串中。
  3. 返回结果:遍历完成后,当前字符串即为解码后的结果。

算法示例#

"3[a2[c]]" 为例,演示算法执行过程:

  • 遇到 3cur_num = 3
  • 遇到 [:将 (3, "") 压入栈,重置 cur_num = 0, cur_str = []
  • 遇到 acur_str = ['a']
  • 遇到 2cur_num = 2
  • 遇到 [:将 (2, "a") 压入栈,重置 cur_num = 0, cur_str = []
  • 遇到 ccur_str = ['c']
  • 遇到 ]:弹出 (2, "a")cur_str = ["a" + 2 * "c"] = ["acc"]
  • 遇到 ]:弹出 (3, "")cur_str = ["" + 3 * "acc"] = ["accaccacc"]
  • 返回 "accaccacc"

时间复杂度#

  • 时间复杂度O(n)O(n),其中 n 是解码后字符串的长度。每个字符最多被处理一次。
  • 空间复杂度O(n)O(n),栈的空间复杂度取决于嵌套层数,最坏情况下为 O(n)O(n)

代码实现#

class Solution:
def decodeString(self, s: str) -> str:
stk: List[Tuple[int, str]] = []
cur_num = 0
cur_str = []
i = 0
while i < len(s):
c = s[i]
if c.isdigit():
res = ''
while s[i].isdigit():
res += s[i]
i += 1
cur_num = int(res)
i -= 1
elif c == '[':
stk.append((cur_num, ''.join(cur_str)))
cur_num = 0
cur_str = []
elif c == ']':
pre_num, pre_str = stk.pop()
cur_str = [pre_str + pre_num * ''.join(cur_str)]
else:
cur_str.append(c)
i += 1
return ''.join(cur_str)

Some information may be outdated

封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00