问题描述
小M拿到了一个由小写字母组成的字符串 s。她发现可以进行一种操作:选择两个相邻且相同的字母并删除它们。她可以在 s 上反复进行此操作,直到无法再删除任何字母。
请返回最终处理完所有重复项删除操作后的字符串。可以保证返回的答案是唯一的。
测试样例
样例1:
输入:
s = "abbaca"
输出:'ca'
样例2:
输入:
s = "azxxzy"
输出:'ay'
样例3:
输入:
s = "a"
输出:'a'
结果展示
def solution(s: str) -> str:
stack = [] # 初始化栈
for char in s:
if stack and stack[-1] == char:
stack.pop() # 删除相邻重复的字符
else:
stack.append(char) # 压入当前字符
return ''.join(stack) # 将栈中的字符合并为字符串
if __name__ == '__main__':
print(solution(s="abbaca") == 'ca')
print(solution(s="azxxzy") == 'ay')
print(solution(s="a") == 'a')
`
题目解析
题目要求
给定一个仅由小写字母组成的字符串 s,通过反复执行以下操作:找到两个相邻且相同的字符并删除它们,直到字符串中再无可删除的字符为止。返回最终剩余的字符串。
核心思路
-
借助栈:栈是一种后进先出的数据结构,非常适合处理这一类相邻字符配对消除的操作。
-
逐个遍历字符串:
- 如果当前字符和栈顶字符相同,则删除栈顶元素(模拟“消除”)。
- 如果不同,将当前字符压入栈。
-
最终结果:栈中的元素就是处理后的字符串,从栈底到栈顶依次输出即可。
图解
以输入 s = "abbaca" 为例:
| 当前字符 | 栈状态(处理后) | 操作描述 |
|---|---|---|
'a' | ['a'] | 第一个字符入栈 |
'b' | ['a', 'b'] | 不同字符入栈 |
'b' | ['a'] | 栈顶 'b' 相同,出栈 |
'a' | [] | 栈顶 'a' 相同,出栈 |
'c' | ['c'] | 不同字符入栈 |
'a' | ['c', 'a'] | 不同字符入栈 |
最终栈内容为 ['c', 'a'],输出结果为 'ca'。
代码详解
def solution(s: str) -> str:
# 初始化栈,用于存放字符
stack = []
# 遍历字符串
for char in s:
# 栈非空且当前字符与栈顶相同时,消除栈顶
if stack and stack[-1] == char:
stack.pop()
else:
# 否则,将当前字符压入栈
stack.append(char)
# 将栈中的字符合并为最终字符串返回
return ''.join(stack)
# 测试用例
if __name__ == '__main__':
print(solution("abbaca") == 'ca') # 测试样例1
print(solution("azxxzy") == 'ay') # 测试样例2
print(solution("a") == 'a') # 测试样例3
代码详解
- 栈初始化:
stack = []用于模拟字符串的“消除”过程。 - 遍历字符串:逐字符判断是否与栈顶相同,决定是“出栈”还是“入栈”。
- 合并栈元素:最后通过
''.join(stack)将栈中的字符拼接为字符串。
知识总结
-
栈的应用场景
- 栈常用于需要“回溯”或“配对”的场景。例如括号匹配问题、消除问题等。
- 特点:后进先出,模拟类似递归和消除的过程。
-
解题经验
- 遇到**“连续消除”类型问题时,可以优先考虑用栈**来处理。
- 栈的常用操作:
push(压入)、pop(弹出)、peek(查看栈顶元素)、isEmpty(是否为空)。
-
学习建议
- 熟悉栈的操作,理解其在递归、深度优先搜索中的作用。
- 刷题过程中,尽量用图解来帮助理解问题的本质。
-
其他注意点
- 注意边界情况:如空字符串、只有一个字符的字符串等。
- 熟练使用 Python 的
list数据结构来模拟栈。
对入门同学的学习建议
- 理解核心思路:不要急着写代码,先用纸笔画图模拟一遍问题,理解栈如何帮助解决“相邻字符消除”的问题,这样可以更深入的了解题目要求和更好的理解。
- 多动手实践:将不同输入输出的场景逐一测试,从而加深理解。
- 总结模式:类似的“消除”问题都可以归类到一个“解题框架”中。
- 提升难度:尝试将题目扩展,比如对更复杂的规则或字符串进行操作。