当前位置: 首页 > news >正文

【LeetCode 热题 100】155. 最小栈

Problem: 155. 最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(1)
    • 空间复杂度:O(N)

整体思路

这段代码旨在实现一个经典的特殊数据结构:最小栈 (Min Stack)。这个数据结构除了支持常规栈的 pushpoptop 操作外,还必须支持一个 getMin 操作,该操作能够以 常数时间 O(1) 返回栈中当前的最小元素。

该算法的核心思想是,不只在栈中存储元素值本身,而是 将每个元素与其“当时”的栈内最小值绑定在一起存储

  1. 数据结构选择

    • 算法选择了一个双端队列 Deque<int[]> 并将其用作栈。
    • 关键在于,栈中存储的不是单个整数,而是一个大小为 2 的整型数组 int[]。这个数组被设计成一个元组(pair){value, current_minimum}
      • pair[0] 存储的是被 push 进栈的实际值 val
      • pair[1] 存储的是当这个 val 被压入时,栈内所有元素(包括 val)的最小值
  2. 核心操作逻辑

    • push(val): 当一个新值 val 被推入栈时,算法会创建一个新的元组。新元组的第二部分(current_minimum)通过比较 val上一个状态的最小值(即当前栈顶元组的第二部分 getMin())来确定。这样,每个层级的栈都“知道”自己及以下所有元素的最小值。
    • getMin(): 由于每个状态都保存了到它为止的最小值,获取整个栈的最小值就变得非常简单:只需查看当前栈顶元组的第二部分 st.peek()[1] 即可。这是一个 O(1) 操作。
    • top(): 获取栈顶元素的值,同样只需查看当前栈顶元组的第一部分 st.peek()[0]
    • pop(): 弹出栈顶元组。这个操作非常巧妙,因为当一个元组被弹出后,新暴露出的栈顶元组中保存的最小值,就自动地变回了上一个状态的最小值,无需任何额外计算。
  3. 初始化处理

    • 构造函数中 st.push(new int[]{0, Integer.MAX_VALUE}); 的操作是一个哨兵节点(Sentinel Node)。它的目的是简化 push 操作的逻辑。通过预置一个最小值为 Integer.MAX_VALUE 的节点,第一次调用 push 时,Math.min(getMin(), val) 就能自然地得到 val 作为第一个真正的最小值,从而避免了在 push 方法中写 if (st.isEmpty()) 的特殊判断。

完整代码

/*** 一个支持在常数时间内检索到最小元素的栈。*/
class MinStack {// 使用 Deque 作为栈的底层实现。// 存储的是一个大小为2的数组,格式为 {value, current_minimum}。private final Deque<int[]> st = new ArrayDeque<>();/*** 构造函数,初始化最小栈。*/public MinStack() {// 推入一个哨兵节点或初始节点。// Integer.MAX_VALUE 确保第一个被推入的真实元素的最小值就是它自身。// 这样可以避免在 push 方法中对空栈进行特殊处理。st.push(new int[]{0, Integer.MAX_VALUE});}/*** 将元素 val 推入栈中。* @param val 要推入的元素值*/public void push(int val) {// 创建一个新的元组 {val, min(当前最小值, val)}。// getMin() 会返回上一个状态的最小值。// 将新值与上一个状态的最小值比较,得到新的当前最小值。st.push(new int[]{val, Math.min(getMin(), val)});}/*** 删除栈顶的元素。*/public void pop() {// 直接弹出栈顶的元组 {value, current_minimum}。// 栈的状态(包括最小值)会自动恢复到上一个状态。st.pop();}/*** 获取栈顶元素。* @return 栈顶元素的值*/public int top() {// 栈顶元组的第一个元素 [0] 存储的是实际值。return st.peek()[0];}/*** 在常数时间内检索到栈中的最小元素。* @return 栈中的最小元素值*/public int getMin() {// 栈顶元组的第二个元素 [1] 存储的是到当前状态为止的最小值。return st.peek()[1];}
}

时空复杂度

时间复杂度:O(1)

  1. push(val): 该操作包括 getMin() (即 peek)、Math.minst.push()。对于 ArrayDeque,这些都是 O(1) 的均摊时间复杂度。
  2. pop(): st.pop()O(1) 的均摊时间复杂度。
  3. top(): st.peek()O(1) 的时间复杂度。
  4. getMin(): st.peek()O(1) 的时间复杂度。

综合分析
该数据结构的所有公开操作(push, pop, top, getMin)都具有 O(1) 的时间复杂度,满足了设计要求。

空间复杂度:O(N)

  1. 主要存储开销:空间复杂度由栈 st 的大小决定。
  2. 空间大小:对于用户推入的每一个元素,我们都在栈中存储一个包含两个整数的数组 int[]。如果栈中有 N 个元素(不包括哨兵节点),那么实际存储了 Nint[2] 对象。
  3. 综合分析
    所需的额外空间与栈中元素的数量 N 成线性关系。因此,空间复杂度为 O(N)

参考灵神

http://www.dtcms.com/a/309146.html

相关文章:

  • PL-0功能拓展及基于VSCode的IDE配置
  • kotlin语法和特性分析
  • PDFsam免费开源!PDF分割合并工具
  • 华为数通HCIP
  • 为什么我们需要提示词增强工程PEE(Prompt Enhancement Engineering )
  • axios请求的取消
  • ICML 2025 | 深度剖析时序 Transformer:为何有效,瓶颈何在?
  • Qt Quick 3D 基础与应用
  • 【数据结构初阶】--排序(一):直接插入排序,希尔排序
  • zabbix平台无法删除已停用主机的处理案例
  • 基于springboot的快递分拣管理系统
  • 信号发生器和示波器阻抗匹配问题
  • 重生之我在暑假学习微服务第七天《微服务之服务治理篇》
  • flutter设备图标颜色与字体颜色相同自动适配明与暗的模式
  • 力扣 hot100 Day62
  • UnityURP 使用StencilBuffer制作一个“看见看不见”的球
  • 第三方采购流程
  • 前端图片懒加载的深度指南:从理论到实战
  • 使用 whisper, 音频分割, 初步尝试,切割为小块,效果还不错 1
  • java对象的内存分配
  • linux编译基础知识-工具链
  • datagrip连接mysql数据库过程以及遇到的问题
  • Linux网络:多路转接 epoll
  • 深入讲讲异步FIFO
  • Blender 4.5 安装指南:快速配置中文版,适用于Win/mac/Linux系统
  • 汽车EDI:Vitesco EDI 项目案例
  • 基于单片机汽车少儿安全预警系统
  • 【世纪龙科技】汽车整车维护仿真教学软件-智构整车维护实训
  • Oracle EBS ERP开发 — 抛出异常EXCEPTION书写规范
  • 【世纪龙科技】3D交互深度赋能-汽车整车维护仿真教学软件