跳到正文
第 394 题中等

字符串解码

Decode String

解码形如 k[encoded] 的字符串,支持嵌套和多位数字。

在力扣中练习

题目描述

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

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

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

测试用例保证输出的长度不会超过 105。

 

示例 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 <= 30
  • s 由小写英文字母、数字和方括号 '[]' 组成
  • s 保证是一个 有效 的输入。
  • s 中所有整数的取值范围为 [1, 300] 

解题思路

主解法

双栈 · 迭代

数字栈存重复次数,字符串栈存外层已解出的内容

括号可能嵌套,所以需要记住“进入这一层之前”的状态。用两个栈:

  • counts 存每层的重复次数;
  • strs 存每层外面的字符串。

读到数字就累积 num;读到 [ 就把 num 和当前 cur 压栈,然后清零;读到字母就追加到 cur;读到 ] 就弹出 k 和外层字符串,把 cur 重复 k 次接回去。

分步图解

遇到数字先累积;遇到 [ 把 num 和外层 cur 压栈;遇到 ] 弹出并重复拼接。

输入 · 已读 / 当前字符
0
1
2
3
4
5
6
7
8
9
10
11
3
[
a
2
[
c
]
]
4
[
b
]
当前状态
num=0cur=""
counts · 栈底 → 栈顶
空
最右侧是栈顶;遇到 ] 时从这里弹出最近一层的重复次数。
strs · 栈底 → 栈顶
空
保存进入括号前已经解出的外层字符串,出栈后接回。
1 / 5
外层 3 与字符串压栈后,内层 2 再压一层;cur 只保存当前层的内容。

自拟串 "3[a2[c]]4[b]" 有两层嵌套:内层 2[c] 先展开成 cc,外层再把 a+cc 重复三次;最后的 4[b] 与外层互不影响。

分步图解

进入新一层:把重复次数和外层字符串压栈,num、cur 清零。

depth
2
输入 · 已读 / 当前字符
0
1
2
3
4
5
6
7
8
9
10
11
3
[
a
2
[
c
]
]
4
[
b
]
i
当前状态
num=0cur=""
counts · 栈底 → 栈顶
3
2
最右侧是栈顶;遇到 ] 时从这里弹出最近一层的重复次数。
strs · 栈底 → 栈顶
""
a
保存进入括号前已经解出的外层字符串,出栈后接回。
1 / 4
遇到 ] 先展开内层,再遇到外层 ] 把 acc 重复三次;两个栈同步回退。

每个字符只处理一次,重复拼接的总量等于输出长度,时间与输出规模同阶;空间 O(嵌套深度 + 输出)。

时间 O(n + 输出长度)空间 O(嵌套深度)

易错点

  • 数字只取一位:遇到 12[ab] 会解码错。
  • [ 时忘记保存外层字符串:嵌套结束后接不回去。
  • ] 时先拼再弹栈:顺序反了会用错外层。
  • 用递归但忘记跳过 ]:会在右括号处死循环。
对照解法

递归 · 解析每一层

遇到 [ 就递归解析内层,返回后重复拼接

代码更短,但递归深度等于嵌套层数,极深输入可能栈溢出;双栈版把调用栈显式化。

把每一对括号看成一次递归:遇到 [ 就进入下一层,解析到匹配的 ] 返回内层字符串,再按前面的数字重复。

递归函数的循环在遇到 ] 或字符串结束时退出,正好把当前层的内容交回给调用者。数字在每层各自累积,不会互相干扰。

它和双栈版状态一一对应,只是把“保存外层字符串”交给调用栈。

  1. 1逐字符解析当前层。
  2. 2遇到 [ 递归解析内层。
  3. 3返回后按 num 重复并接到当前结果。
  4. 4遇到 ] 或末尾返回当前层字符串。
时间 O(n + 输出长度)空间 O(嵌套深度)

易错点

  • 递归返回后忘记跳过 ]:外层会把右括号当普通字符。
  • num 没有在每层清零:内层数字污染外层。
  • 重复次数很大时直接递归拼接:输出规模本身无法避免。

代码与演示

主解法配有图解;对照解法用于比较思路、复杂度或实现方式。

演示输入s = "3[a2[c]]4[b]"

遇到数字先累积;遇到 [ 把 num 和外层 cur 压栈;遇到 ] 弹出并重复拼接。

输入 · 已读 / 当前字符
0
1
2
3
4
5
6
7
8
9
10
11
3
[
a
2
[
c
]
]
4
[
b
]
当前状态
num=0cur=""
counts · 栈底 → 栈顶
空
最右侧是栈顶;遇到 ] 时从这里弹出最近一层的重复次数。
strs · 栈底 → 栈顶
空
保存进入括号前已经解出的外层字符串,出栈后接回。
1 / 11
查看 C++ 代码

延伸阅读

  • 括号嵌套题通常需要两个栈:一个存数值,一个存“进入括号前”的上下文。
  • 如果只需要求解码后的第 k 个字符,可以边解析边计数,避免构造完整字符串。