题目重点:用字符栈模拟 # 的退格效果,覆盖开头退格、连续退格、空输入和输出结果。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版把 # 解释为删除当前结果最后一个仍存在的字符;当结果为空时忽略 #。
- 输入字母不含 # 以外的控制字符,不讨论 Unicode grapheme cluster;若“前一个字母”指原始文本左邻而非存活字符,需改题意。
解题路线
- 普通字符压入栈,遇 # 若栈非空则弹出;扫描完成把栈连接成结果。
- 不变量:处理到任意前缀时,栈从底到顶就是该前缀全部退格后的有效字符序列;下一字符只需影响末尾。
- 若只比较两个退格字符串而不要求实际结果,可从右往左用 skip 计数以 O(1) 额外空间,但本题需要输出,因此栈简单直接。
手动走一遍
ab#c##d:a、b 入栈,# 删 b,c 入栈,两个 # 分别删 c 和 a,最后 d 入栈,返回 d。###a 的开头多余退格按训练约定忽略,返回 a。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
"""Apply # as deletion of the previous surviving character."""
def apply_backspaces(value: str) -> str:
stack: list[str] = []
for char in value:
if char == "#":
if stack:
stack.pop()
else:
stack.append(char)
return "".join(stack)
复杂度
N 个字符单次扫描 O(N) 时间,最坏 O(N) 栈与输出空间;空字符串 O(1)。
易错点与追问
容易失分的边界
- 遇连续 ## 只删一个字符。
- 空栈仍 pop 导致异常,而题目未给多余退格处理。
- 在原字符串上反复切片删除,可能退化为 O(N²)。
继续深挖
- 若退格字符带次数,例如 #3,如何解析和高效处理?
- 若只判断两个字符串退格后是否相等,如何不构造完整结果?
