Leetcode 316. 去除重复字母
单调栈 + 贪心思想。加了详细的注释,方便日后复习,也希望能帮到其他小伙伴,如有错误,欢迎指正!
class Solution:
def removeDuplicateLetters(self, s: str) -> str:
# 初始化一个栈,等会儿用来做单调栈使用(虽然这道题的单调栈不是严格意义上的单调栈,但是思想是一致的)
stack = []
# 记录每一种字母的剩余次数
remain_s = collections.Counter(s)
# 遍历字符串中每一个字母
for i in s:
# 如果栈中没有该字母,说明该字母需要加入到栈中
if i not in stack:
"""由于题目要求需要使得返回结果的字典序最小,也就是在不打乱字符的相对顺序的前提下,尽可能贪心地让小的字母排在前面即可;
为了达到上述目的,我们只要比较当前遍历的元素和栈顶元素的大小,如果当前元素小就不断地从栈顶弹出元素(不过有两个前提:
1)栈中仍有元素;2)后面还会遍历到这个被弹出的元素,否则后面不出现,栈中也没有这个元素了,那该字母就彻底不可能出现了)"""
while stack and i < stack[-1] and remain_s[stack[-1]] > 0:
stack.pop()
# 知道当前遍历到的元素比栈顶元素(虽然stack不是严格意义的单调栈,但是此时栈顶的元素是维持不打乱相对顺序的最大元素)都大,
# 就把这个元素添加到栈顶即可
stack.append(i)
"""前面有if,所以有两种情况,第一种情况,可能栈中已经有该字母了,这种情况直接令该字母的剩余次数-1
第二种情况,栈中没有该字母,那就将字母添加到栈中的合适位置后,该字母的剩余次数-1,但是处理方式在此处是一致的"""
remain_s[i] -= 1
# 返回单调栈拼接成字符串的结果
return "".join(stack)