返回

解谜LeetCode第37题:揭秘去除重复字母的巧妙算法

前端

去除重复字母:巧妙算法揭秘

当我们处理包含重复字母的字符串时,去除这些重复字母以获得一个更精简的、字典序最小的字符串就显得非常重要。在本文中,我们将深入探讨一种巧妙的算法,它结合了单调栈和哈希表,以高效而优雅的方式解决这一难题。

单调栈:有序序列的守护者

单调栈是一种特殊类型的栈,它保持其元素的顺序要么单调递增,要么单调递减。在我们的场景中,我们将利用单调栈来维护字母的字典序。

算法从字符串开头开始遍历。对于每个字母,它与栈顶元素进行比较。如果当前字母较小,且后续字符中存在该字母的重复项,那么栈顶元素就会被弹出,为当前字母腾出空间。然后,当前字母被压入栈顶,保持字典序的递增顺序。

哈希表:追踪字母的足迹

哈希表是一个强大的数据结构,用于记录字母在字符串中的位置和是否存在。在我们的算法中,它扮演着至关重要的角色,确保我们不会错过任何重复字母。

当遍历字符串时,如果当前字母在哈希表中不存在,它将直接被添加到栈中。然而,如果该字母已存在,并且其位置大于栈顶元素的位置,那么栈顶元素就会被弹出。这样,我们可以继续在栈中维护字典序的递增顺序。

算法流程:精妙而高效

现在,让我们将单调栈和哈希表结合起来,构建去除重复字母的算法流程:

  1. 初始化 单调栈和哈希表。
  2. 遍历 字符串,依次处理每个字母。
  3. 检查 当前字母在哈希表中是否存在。
  4. 如果不存在 ,直接压入栈中。
  5. 如果存在 ,并且位置大于栈顶元素,弹出栈顶元素。
  6. 将当前字母压入栈中 ,并更新其在哈希表中的位置。
  7. 重复步骤 3-6 ,直至遍历完字符串。
  8. 弹出栈中字母 ,得到去除重复字母后的字符串。

代码示例:揭开算法的神秘面纱

def remove_duplicate_letters(s: str) -> str:
    """
    去除字符串中重复的字母,字典序最小

    :param s: 输入字符串
    :return: 去除重复字母后,字典序最小的字符串
    """
    stack = []  # 单调栈
    visited = {}  # 哈希表

    for i, c in enumerate(s):
        if c not in visited:
            while stack and stack[-1] > c and s.find(stack[-1], i) != -1:
                stack.pop()
            stack.append(c)
            visited[c] = True
    
    return ''.join(stack)

结论:拥抱简洁与高效

去除重复字母的巧妙算法通过巧妙地结合单调栈和哈希表,提供了一种高效而优雅的解决方案。它不仅能够去除重复字母,还确保了字典序最小,从而节省了时间和空间。

常见问题解答

1. 单调栈的优势是什么?
单调栈允许我们在遍历字符串时维护字母的字典序,从而确保输出字符串的字典序最小。

2. 哈希表的用途是什么?
哈希表用于追踪字母的位置和是否存在,确保我们在处理重复字母时不会错过任何一个。

3. 该算法的时间复杂度是多少?
算法的时间复杂度为 O(n),其中 n 是字符串的长度。

4. 该算法的空间复杂度是多少?
算法的空间复杂度为 O(n),因为单调栈和哈希表中最多存储 n 个字母。

5. 这种算法可以应用在哪些其他场景中?
这种算法可以应用于任何需要去除重复元素并保持元素顺序的场景,例如:

  • 合并多个有序数组
  • 从链表中去除重复元素
  • 在字符串中找到最长的不重复子串