返回

单调栈解题:优雅高效获取字符串中最小的子序列!

后端

导语:单调栈简介

单调栈是一种数据结构,它可以存储一组元素,并且栈顶元素始终满足某种单调性。在本文中,我们将使用单调栈来解决 LeetCode 1081:Smallest Subsequence of Distinct Characters 的问题。该问题要求我们从给定字符串中找出最小的子序列,使得该子序列中的所有字符都是不同的。

单调栈实现:探索核心算法

为了解决这个问题,我们可以使用单调栈来存储字符串中的字符。我们从字符串的第一个字符开始,依次遍历字符串中的每个字符。对于每个字符,我们将其与栈顶元素进行比较。如果当前字符比栈顶元素大,则我们将当前字符压入栈中。如果当前字符比栈顶元素小,则我们将栈顶元素弹出,并继续比较当前字符与新的栈顶元素。

代码实现:一步步剖析单调栈应用

def smallest_subsequence(s):
    # 创建一个单调栈
    stack = []

    # 创建一个哈希表来存储每个字符的最新位置
    last_seen = {}

    # 遍历字符串中的每个字符
    for i in range(len(s)):
        # 如果当前字符不在哈希表中,则将其添加到哈希表中
        if s[i] not in last_seen:
            last_seen[s[i]] = i

        # 如果当前字符比栈顶元素大,则将其压入栈中
        if not stack or s[i] > stack[-1]:
            stack.append(s[i])

        # 如果当前字符比栈顶元素小,则将栈顶元素弹出,并继续比较当前字符与新的栈顶元素
        else:
            while stack and s[i] < stack[-1] and last_seen[stack[-1]] > i:
                stack.pop()

            # 将当前字符压入栈中
            stack.append(s[i])

    # 返回栈中的所有字符
    return ''.join(stack)

# 示例用法
s = "cdadabcc"
result = smallest_subsequence(s)
print(result)  # 输出:"adbc"

优化技巧:提升单调栈应用效率

为了进一步提升单调栈的应用效率,我们可以使用一些优化技巧。例如,我们可以使用哈希表来存储每个字符的最新位置。这样,当我们遇到一个比栈顶元素小的字符时,我们可以直接弹出栈顶元素,而无需遍历整个栈。

扩展应用:单调栈在编程中的其他妙用

除了解决 LeetCode 1081:Smallest Subsequence of Distinct Characters 的问题外,单调栈还可以用于解决许多其他问题。例如,我们可以使用单调栈来求解最长上升子序列、最长下降子序列、最大连续子数组和等问题。

总结:单调栈的魅力与价值

单调栈是一种简单而强大的数据结构,它可以在许多问题中发挥重要作用。通过使用单调栈,我们可以有效地解决一些复杂的编程问题。希望本文对您理解单调栈的原理和应用有所帮助。