实现一个支持 push(入栈)、pop(出栈)和 min(获取最小元素)操作的栈数据结构,且三个操作的时间复杂度均为 O(1)

包含 min 函数的栈设计说明

一、设计目标

实现一个支持 push(入栈)、pop(出栈)和 min(获取最小元素)操作的栈数据结构,且三个操作的时间复杂度均为 O(1)

二、核心思路

1. 数据结构选择

使用 两个栈 实现:

  • 主栈(stack):存储所有元素,支持正常的 pushpop 操作。
  • 辅助栈(min_stack):存储当前栈中的 最小元素,确保 min 操作可直接获取栈顶值。

2. 操作逻辑

(1)push 操作(入栈)
  • 主栈:直接将元素压入。
  • 辅助栈
    • 若辅助栈为空,或新元素 小于等于 辅助栈栈顶元素,则将新元素压入辅助栈。
    • 否则,将辅助栈栈顶元素 再次压入(保持与主栈元素数量一致,简化 pop 操作)。
(2)pop 操作(出栈)
  • 主栈:弹出栈顶元素。
  • 辅助栈:同步弹出栈顶元素(因辅助栈与主栈元素数量一致,弹出后仍能反映当前最小元素)。
(3)min 操作(获取最小元素)
  • 直接返回 辅助栈的栈顶元素,即为当前主栈中的最小元素。

三、示例演示

以序列 [3, 2, 5, 1, 4] 为例:

操作主栈(stack)辅助栈(min_stack)当前最小元素(min)
push(3)[3][3]3
push(2)[3, 2][3, 2]2
push(5)[3, 2, 5][3, 2, 2]2
push(1)[3, 2, 5, 1][3, 2, 2, 1]1
push(4)[3, 2, 5, 1, 4][3, 2, 2, 1, 1]1
pop()[3, 2, 5, 1][3, 2, 2, 1]1
pop()[3, 2, 5][3, 2, 2]2

四、复杂度分析

  • 时间复杂度pushpopmin 操作均为 O(1)(仅涉及栈顶元素的访问和修改)。
  • 空间复杂度O(n)(n 为元素个数,辅助栈最多存储 n 个元素)。

五、关键优势

  1. 高效性:所有操作均为常数时间复杂度,满足实时性要求。
  2. 简洁性:通过双栈同步机制,避免复杂的条件判断,逻辑清晰。
  3. 鲁棒性:辅助栈与主栈元素数量一致,pop 操作无需额外判断,避免边界错误。

六、适用场景

  • 需要频繁获取栈中最小元素的场景(如算法题、实时数据监控、表达式求值等)。
  • 对时间效率要求较高的系统,如高频交易、实时排行榜等。

总结

通过 双栈协同 的设计,主栈负责元素存储,辅助栈动态跟踪最小元素,可在 O(1) 时间内完成 pushpopmin 操作。该方案兼顾效率与简洁性,是解决此类问题的经典方法。

使用两个栈实现包含 min 函数的栈结构虽然能满足时间复杂度要求,但存在以下缺点:

一、空间复杂度较高

  • 辅助栈冗余存储:为保持与主栈元素数量一致,辅助栈需重复存储相同的最小元素(如示例中 push(5) 时辅助栈再次压入 2)。在最坏情况下(如元素单调递增),辅助栈与主栈存储完全相同的元素,导致空间复杂度翻倍(从 O(n) 变为 O(2n))。

二、操作同步性要求严格

  • 必须严格同步 pushpop:若主栈与辅助栈的操作不同步(如漏弹辅助栈元素),会直接导致 min 函数返回错误结果。这种强耦合性增加了代码实现的易错性,尤其在多线程环境下需额外处理同步问题。

三、不适用于海量数据场景

  • 当栈中元素数量极大(如百万级)时,辅助栈的冗余存储会显著增加内存占用,可能引发内存溢出风险。对于资源受限的嵌入式系统或高性能要求的场景,该方案不够经济。

四、删除中间元素时逻辑复杂

  • 若扩展需求中涉及删除栈中间元素(非栈顶),双栈结构难以高效支持,需遍历主栈重构辅助栈,导致时间复杂度退化至 O(n),违背原设计初衷。

对比优化方案

  • 单栈+变量记录最小值:可减少空间占用,但 pop 操作可能需要重新计算最小值(时间复杂度退化为 O(n))。
  • 链表+最小值指针:通过节点记录当前最小值,可优化空间,但实现复杂度更高。

综上,双栈方案的核心 trade-off 是用 空间换时间,适用于对时间效率要求极高、空间资源相对充裕的场景,但若需平衡空间开销,需根据实际需求选择其他实现方式。

单栈方案(仅用一个栈存储元素,通过变量记录当前最小值)在弹出栈顶元素恰好是当前最小值时,时间复杂度会退化为 O(n)。具体场景如下:

退化触发条件

当栈顶元素是当前最小值,且执行 pop 操作后,需要重新遍历整个栈以寻找新的最小值。此时 pop 操作的时间复杂度从 O(1) 变为 O(n)。

示例说明

假设栈内元素为 [5, 3, 4, 2, 1],当前最小值为 1(栈顶):

  1. 执行 pop() 弹出 1 后,需遍历剩余元素 [5, 3, 4, 2] 才能找到新的最小值 2,此时遍历耗时 O(n)。

本质原因

单栈方案通过变量记录最小值,但未保存历史最小值序列。一旦当前最小值被弹出,只能通过回溯整个栈重新计算,导致时间复杂度退化。

对比双栈方案

双栈方案通过辅助栈保存每个状态的最小值,即使弹出当前最小值,辅助栈顶仍能直接提供新的最小值,因此所有操作均保持 O(1) 复杂度。

结论

单栈方案的时间复杂度退化发生在 弹出当前最小值 的场景下,此时需遍历栈以更新最小值。这是其为节省空间而牺牲最坏情况效率的典型 trade-off。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值