📌  相关文章
📜  通过从给定字符串删除一个字符,可能的字典序最小子序列(1)

📅  最后修改于: 2023-12-03 14:58:03.781000             🧑  作者: Mango

通过从给定字符串删除一个字符,可能的字典序最小子序列

问题描述:给定一个字符串s,通过从s中仅删除一个字符,找出可能的字典序最小的子序列。

例如:s = "bcabc"。

我们可以删除b和c得到字典序最小的子序列"aabc"。

思路:这是一个典型的栈的应用场景。我们可以用一个栈来维护当前获取的子序列。对于任意一个字符,如果这个字符比栈顶的字符小,并且栈顶的字符在后面还会出现,那么我们就把栈顶的字符弹出。

算法过程:

  1. 我们初始化一个栈和一个字典last_occurrence,用字典记录每个字符最后一次出现的位置。

  2. 遍历字符串s中的每个字符c,执行以下操作:

    a. 如果栈不为空,且c比栈顶元素小,并且栈顶元素在后面还会出现,那么我们就把栈顶元素弹出。

    b. 如果c在last_occurrence中没有记录,我们直接把c压入栈中。

    c. 在last_occurrence中记录c的位置。

  3. 把栈中的元素弹出,这就是我们的最终答案。

代码演示:

def smallest_subsequence(s: str) -> str:
    last_occurrence = {c: i for i, c in enumerate(s)}
    stack = []
    for i, c in enumerate(s):
        if c in stack:
            continue
        while stack and c < stack[-1] and i < last_occurrence[stack[-1]]:
            stack.pop()
        stack.append(c)
    return ''.join(stack)

代码解释:

第一步中,我们用字典last_occurrence记录每个字符最后一次出现的位置,用stack来维护当前的子序列。

第二步中,我们遍历字符s中的每个字符c,执行以下操作:

a. 如果栈不为空,且c比栈顶元素小,并且栈顶元素在后面还会出现,我们就把栈顶元素弹出。

b. 如果c在last_occurrence中没有记录,我们直接把c压入栈中。

c. 在last_occurrence中记录c的位置。

第三步中,我们把栈中的元素弹出,这就是我们的最终答案。

总结:

这是一个经典的栈的应用场景,通过维护一个栈和一个字典,我们可以解决这个问题。这里需要注意的是,在遍历字符串s中的每个字符c时,我们不能直接忽略掉已经在栈中的字符,因为删除栈中的字符,可能会得到更小的字典序子序列。