394. 字符串解码

中等 含交互动画

学完这道你应该能: 说清它为什么用「栈」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

k[内容] 表示把「内容」重复 k 次,可能嵌套。求解码后的字符串。

s = "3[a2[c]]"
输出 = "accaccacc"

思路解析

遇到数字就记重复次数;遇到 [ 就把「当前已拼的串」和「次数」压栈,然后清空重来;遇到 ] 就弹出,把当前串重复 N 次接到弹出的旧串后面。

读到 3,遇到 [:读到数字 3。遇到 [:把 3 压数字栈、当前串(空)压字符串栈,然后清空当前串,进入括号内部。

遇到 [ 的动作叫存档:把当前的「次数」和「已拼字符串」分别压进两个栈,然后清零,进入括号里从头拼。

读到 a,再读 2、[:括号里先读到 a(当前串变 "a")。又遇到 2[:把 2 和 "a" 压栈,再清空当前串。栈在加深,就像进入更里层。

读到 c,遇到 ]:读到 c(当前串 "c")。遇到 ]:弹出次数 2 和旧串 "a",当前串 = 旧串 + "c"重复2次 = "acc"。回到上一层。

遇到 ] 做三件事:弹出次数 k、弹出旧串 prev,然后 cur = prev + cur 重复 k 次。相当于合上这层括号,把结果交回外层。

再遇到 ]:又遇到 ]:弹出次数 3 和旧串(空),当前串 = "acc" 重复 3 次 = "accaccacc"。两个栈都空,解码完成。

每个 [ 让我们「存档、深入一层」,每个 ] 让我们「读档、把这层结果重复后接回去」。栈天生适合嵌套。

遇到嵌套结构(括号、目录、表达式),就用栈把「外层状态」存起来,处理完里层再恢复。基本计算器、简化路径都是它。

参考代码(Python)

Python
1numStack, strStack, cur, num = [], [], class="cl-str">"", 0
2for ch in s:
3    if ch.isdigit(): num = num*10 + int(ch)   # 多位数字
4    elif ch == class="cl-str">"[":
5        numStack.append(num); strStack.append(cur)   # 存档
6        num, cur = 0, class="cl-str">""
7    elif ch == class="cl-str">"]":
8        k = numStack.pop(); prev = strStack.pop()
9        cur = prev + cur * k                  # 读档、重复、拼接
10    else: cur += ch                          # 普通字母
11return cur

复杂度分析

  • 时间复杂度:O(输出长度) —— 每个输出字符生成一次
  • 空间复杂度:O(嵌套深度) —— 两个栈

套路模板

记住骨架:遇「进入」就把外层现场压栈、遇「退出」就弹栈合并、否则累积当前层。注意 num*10+ 处理多位数字(如 12[a])。基本计算器、简化路径都是同款。

Python
1# 括号 / 表达式 / 目录等嵌套结构都套
2stack, cur, num = [], class="cl-str">"", 0
3for ch in s:
4    if ch.isdigit(): num = num*10 + int(ch)        # 多位数字累加!
5    elif ch == class="cl-str">"[": stack.append((cur,num)); cur,num = class="cl-str">"",0   # 存档
6    elif ch == class="cl-str">"]": prev,k = stack.pop(); cur = prev + cur*k  # 读档合并
7    else: cur += ch
8return cur

易错点

  • 数字只读一位 → ✅ num = num*10 + 当前数字(次数可能多位,如 12[a])
  • ] 时拼成 cur*k + prev → ✅ prev + cur*k(旧串在前、重复的新串在后,顺序别反)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →121. 买卖股票的最佳时机 ← 返回题库