316. 去除重复字母

题目描述

给了一个字符串s,需要删除重复的字符。
要求是(1)每个字母只保留一次;(2)结果的字典序最小

f1-贪心+单调栈

基本分析

  1. 如果给定一个s,只能删除一个,怎么删可以使字典序最小?从左到右删除第一个s[i]>s[i+1]的值,比如456651,删除第二个6;987,删除9。
  2. 结合上面的思路,怎么能让字典序尽量的小?遍历字符串,用一个栈来进行维护,保证里面的字符单调递增
  3. 字符保留和单调递增有冲突,怎么维护?只剩一次的时候就不删了;之前出现过就pass。用vis记录栈中的元素访问情况;用cnt记录元素剩余的可用次数,pass掉或者弹出时,可用次数-1。

代码

class Solution:
def removeDuplicateLetters(self, s: str) -> str:
vis = set()
cnt = Counter(s)
stk = []
n = len(s)
for i, ch in enumerate(s):
if ch in vis:
cnt[ch] -= 1
continue
while stk and s[stk[-1]] > ch:
if cnt[s[stk[-1]]] == 1:
break
else:
top = stk.pop()
vis.remove(s[top])
cnt[s[top]] -= 1
stk.append(i)
vis.add(ch)
return "".join([s[i] for i in stk])

总结

  1. 单调栈的两个特性,下标递增+下标对应的内容有某种规律
  2. 结果可以在栈中,也可以只把栈当工具,结果在数组中
  3. 有矛盾的约数的时候,其中一个只是限制条件
posted @   zhangk1988  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示