题目重点:一出现三个相邻相同字母就消除,重复直到稳定;用字符计数栈一次扫描。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版从左到右读取,末尾一旦形成恰好三个相同字符立刻删除;这是明确的操作顺序,若面试官要求每轮同时消除所有三连,结果可能不同。
- 输入仅按字符相等判断,可为空;输出字符串代表剩余序列。
解题路线
- 栈里每项保存当前未消除结果的字符和该字符在栈顶连续出现的次数,计数只会是 1 或 2。
- 新字符等于栈顶时计数加一,达到 3 立即弹出;不同则压入新项。弹出后下一字符可能与暴露的旧栈顶合并,因此自然支持跨段连锁。
- 不变量:处理前缀后的栈展开后等于按训练顺序完全消除该前缀的结果,栈中任何 run 长度都小于 3。新字符只影响末尾,所以局部更新足够。
手动走一遍
aabbba:读到 bbb 后删除,留下 aa;最后 a 使 aaa,再删除,结果空串。aaaa 则前三个 a 消除,留下一个 a。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
"""Eliminate each triple as soon as it appears, allowing cascading removals."""
def remove_triples(value: str) -> str:
stack: list[list[str | int]] = []
for char in value:
if stack and stack[-1][0] == char:
stack[-1][1] += 1
if stack[-1][1] == 3:
stack.pop()
else:
stack.append([char, 1])
return "".join(char * count for char, count in stack)
复杂度
每字符入栈或更新、最多弹出一次,O(N) 时间;最坏 O(N) 栈空间,输出 O(N)。若字符频繁交替,栈长度接近 N。
易错点与追问
容易失分的边界
- 只做一轮字符串替换,漏掉新相邻字符形成的三连。
- 把出现次数为 4 的 run 一次全删;即时三连规则下应剩 1 个。
- 未澄清同时消除与从左到右即时消除的差异。
继续深挖
- 若阈值改为 k,如何处理 k=1 与超长 run?
- 若每轮同时删除所有长度至少三的 run,怎样定义并实现?
