题目描述
k[内容] 表示把「内容」重复 k 次,可能嵌套。求解码后的字符串。
思路解析
直觉是「找到 k[...] 替换成重复 k 次」,但括号可以无限嵌套(3[a2[c]]),你不知道哪个 ] 配哪个 [,从外往里根本对不齐。难点就是嵌套。
转折:嵌套 = 进出层,而栈天生管进出。维护一个当前串 cur 和当前次数 num。遇 [ 就把「num 和已拼的 cur」存档进两个栈、清空重来;遇 ] 就读档:弹出次数 k 和旧串 prev,令 cur = prev + cur×k。从里往外,每层闭合时正好结算。
读 '3':从左往右扫。读到数字 3,记下重复次数 num=3。两个栈都还空着。
读 '[' · 存档:遇到 [:存档!把次数 3 和当前串(空)分别压进两个栈,再清空 num、cur,从括号里头重新开始拼。
读 'a':读到字母 a,不是括号也不是数字,直接接到当前串后面:cur = "a"。
读 '2':读到数字 2,记下 num=2。它要修饰的是后面那个括号里的内容。
读 '[' · 再存档(更深一层):又遇到 [:再次存档,把 2 和 "a" 压栈,清空当前层。两个栈都长高了——这就是「进入更里一层」。
读 'c':在最里层读到 c,接到当前串:cur = "c"。
读 ']' · 读档(合上里层):遇到 ]:读档!弹出次数 2 和旧串 "a",令 cur = 旧串 + 这层串重复 2 次 = "acc"。栈各弹掉一层,回到外层。
读 ']' · 再读档(合上外层):又遇到 ]:弹出次数 3 和旧串(空),cur = "acc" 重复 3 次 = "accaccacc"。两个栈都空了。
扫描结束:整个 s 扫完,栈空,cur = "accaccacc" 就是解码结果。每个 [ 存一次档、每个 ] 读一次档,嵌套就这么被栈理顺了。
遇到嵌套结构(括号、目录、表达式),就用栈把「外层状态」存起来,处理完里层再恢复。基本计算器、简化路径都是它。
参考代码(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])。基本计算器、简化路径都是同款。
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(旧串在前、重复的新串在后,顺序别反)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。