在问 · 算法题解

1047. 删除字符串中的所有相邻重复项

题目描述

输入只含小写字母的字符串 s。

一次操作可以选出两个紧挨着且相同的字母,把它们一起删掉。删除后两侧的字符会接在一起,可能产生新的相邻相同字母。

一直操作到无法再删为止,返回此时的字符串。题目保证结果唯一。

示例 1
输入:s = "abbaca"
输出:"ca"

解释:先删 bb 得到 aaca,再删 aa 得到 ca。

示例 2
输入:s = "azxxzy"
输出:"ay"

解释:先删 xx 得到 azzy,再删 zz 得到 ay。

数据范围

  • 1 <= s.length <= 10^5
  • s 只含小写英文字母。

解题思路

用栈保存“已经稳定”的结果。从左到右读字符,如果它和栈顶相同,说明两者在删除中间部分后相邻,一起消掉(弹栈);否则压入栈。删除一对后,新的栈顶又可能和下一个字符配对,栈自然处理了这种连锁消除。

为什么正确

栈中从底到顶是已扫描前缀完全消除后的结果,栈中任意相邻两个字符都不相同。

复杂度分析

时间 O(n),空间 O(n)。

易错点

只扫一遍、和原串的前一个字符 s[i-1] 比较是错的:删除后新的相邻关系只存在于结果里,必须和栈顶比较。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def removeDuplicates(self, s: str) -> str:
        stack = []
        for c in s:
            if stack and stack[-1] == c:
                stack.pop()
            else:
                stack.append(c)
        return ''.join(stack)

载入编辑器,自己跑一遍 →

栈与堆 专题的其他题目

查看 栈与堆 全部题目 →