返回

最小栈——精妙设计,常数复杂度下的极值获取

前端

一、认识最小栈

1.1 普通栈与最小栈

栈是一种重要的线性数据结构,遵循“先进后出”(Last In First Out,LIFO)的原则。也就是说,后压入栈的元素最先弹出。普通栈只提供基本操作,如压入(push)、弹出(pop)和获取栈顶元素(top)。

最小栈则是一种特殊的栈,除了提供普通栈的操作外,还额外支持一个操作:获取栈中的最小值。与普通栈不同的是,最小栈在执行压入操作时,除了将元素压入栈中外,还会记录当前最小值,以便在需要时快速返回。

1.2 应用场景

最小栈在实际场景中有着广泛的应用,例如:

  • 查找数组中的最小值: 我们可以将数组中的元素依次压入最小栈,每次压入时记录当前最小值。当需要查找数组中的最小值时,直接从最小栈中获取即可,时间复杂度为O(1)。
  • 维护滑动窗口的最小值: 在处理滑动窗口问题时,我们可以使用最小栈来维护窗口中的最小值。当窗口滑动时,我们将新元素压入最小栈,并弹出超出窗口范围的元素。这样,我们就可以在O(1)的时间复杂度内返回滑动窗口中的最小值。
  • 股票交易中的最佳买入和卖出点: 在股票交易中,我们希望在最合适的时间买入和卖出股票以获得最大利润。我们可以使用最小栈来跟踪股票价格的最低点,并在价格上涨时卖出股票。这样,我们就可以在O(1)的时间复杂度内找到最佳的买入和卖出点。

二、最小栈的实现

2.1 基本思路

最小栈的实现思路如下:

  • 使用一个普通栈来存储元素。
  • 使用一个辅助栈来存储最小值。
  • 在压入元素时,将其压入普通栈。如果当前元素小于或等于辅助栈栈顶元素,则将其压入辅助栈。
  • 在弹出元素时,从普通栈弹出元素。如果弹出的元素等于辅助栈栈顶元素,则从辅助栈中弹出元素。
  • 在获取最小值时,直接返回辅助栈栈顶元素即可。

2.2 代码实现(以Python为例)

class MinStack:
    def __init__(self):
        self.stack = []
        self.min_stack = []

    def push(self, x):
        self.stack.append(x)
        if not self.min_stack or x <= self.min_stack[-1]:
            self.min_stack.append(x)

    def pop(self):
        if self.stack.pop() == self.min_stack[-1]:
            self.min_stack.pop()

    def top(self):
        return self.stack[-1]

    def min(self):
        return self.min_stack[-1]

三、常见问题与解决方法

3.1 如何处理空栈的情况?

当栈为空时,我们不能再弹出元素或获取最小值。为了避免这种情况,我们可以对栈进行判空操作,并在空栈时抛出异常或返回特殊值。

3.2 如何处理多个元素相等的情况?

当多个元素相等时,我们可能需要在最小栈中存储多个最小值。我们可以使用一个列表来存储最小值,或者使用一个额外的字段来标记最小值的数量。

3.3 如何处理负数的情况?

当栈中存在负数时,我们需要特别注意最小值的比较。我们可以使用一个比较函数来处理负数的情况,或者使用一个额外的字段来标记负数的数量。

四、结语

最小栈是一种非常实用的数据结构,在许多实际场景中都有着广泛的应用。通过使用最小栈,我们可以