图解LeetCode——剑指 Offer 30. 包含min函数的栈

简介: 图解LeetCode——剑指 Offer 30. 包含min函数的栈

一、题目

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 minpushpop 的时间复杂度都是 O(1)

二、示例

2.1> 示例:

MinStack minStack = new MinStack();

minStack.push(-2);

minStack.push(0);

minStack.push(-3);

minStack.min();   --> 返回 -3.

minStack.pop();

minStack.top();      --> 返回 0.

minStack.min();   --> 返回 -2.

提示:

  • 各函数的调用总次数不超过 20000

三、解题思路

3.1> 维护不完整的有序栈

  • 根据题目描述,我们需要定义一个栈结构stack,来支持实现MinStack类的push()pop()top()方法。但是对于min()方法来说,它是用来返回当前堆栈中最小元素的,那么我们可以再创建一个栈结构stackOrder,用来保存一个“不完整”的有序栈,其存储规则如下所示:

当新元素x小于/等于 stackOrder的栈顶元素时,元素x可以保存到stackOrder的栈顶。

当新元素x大于 stackOrder的栈顶元素时,元素x不执行入栈操作。

  • 那么通过如上规则,stackOrder中的元素就是从栈顶开始,自上而下逐一变大的,而栈顶就是当前最小的元素。
  • 我们讲完了入栈规则,那么出栈呢?针对于stackOrder来说,出栈规则如下所示:

当stack的栈顶元素等于 stackOrder的栈顶元素 时,stack和stackOrder的栈顶元素都出栈。

当stack的栈顶元素不等于 stackOrder的栈顶元素 时,只有stack的栈顶元素出栈。

  • 好了,基本解题思路描述完毕了,下面我们举例,以分别入栈-20-3,然后再执行3次出栈操作,再来看一下stackstackOrder是如何处理的。具体逻辑如下所示:

3.2> 利用元素记录“入栈那一刻”的最小值

  • 那么除了上面的解题思路外,我们其实也可以创建一个Node节点,里面具有如下3个属性:

int value】当前元素的值;

int min】当前所有入栈元素中,最小的值;

Node pre】前一个入栈元素节点;

  • 那么,针对MinStack类的push()pop()top()方法,我们就可以通过构件一个Node链表来实现底层逻辑。而针对min()方法来说,因为每个Node节点都保存了它入栈之前所有入栈元素中,最小的值min,所以直接返回当前节点的min值就可以了。此处就不画图了,具体逻辑可以看下面4.2的源码实现不分。

四、代码实现

4.1> 维护不完整的有序栈

classMinStack {
privateDeque<Integer>stack, stackOrder;
publicMinStack() {
stack=newArrayDeque<>();
stackOrder=newArrayDeque<>();
    }
publicvoidpush(intx) {
stack.addLast(x);
if (stackOrder.isEmpty() ||min() >=x) stackOrder.addLast(x);
    }
publicvoidpop() {
intx=stack.removeLast();
if (min() ==x) stackOrder.removeLast();
    }
publicinttop() {returnstack.getLast();}
publicintmin() {returnstackOrder.getLast();}
}

4.2> 利用元素记录“入栈那一刻”的最小值

classMinStack {
publicNodetop;
publicMinStack() {}
publicvoidpush(intx) {
top=newNode(x, top==null?x : Math.min(x, top.min), top);
    }
publicvoidpop() {top=top.pre;}
publicinttop() {returntop.value;}
publicintmin() {returntop.min;}
}
classNode {
publicintvalue, min;
publicNodepre;
publicNode(intvalue, intmin, Nodepre) {
this.value=value;
this.min=min;
this.pre=pre;
    }
}


今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

相关文章
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
57 6
|
1月前
【LeetCode 24】225.用队列实现栈
【LeetCode 24】225.用队列实现栈
12 0
|
1月前
|
算法
【LeetCode 23】232.用栈实现队列
【LeetCode 23】232.用栈实现队列
19 0
|
3月前
|
算法 Python
【Leetcode刷题Python】剑指 Offer 33. 二叉搜索树的后序遍历序列
本文提供了一种Python算法,用以判断给定整数数组是否为某二叉搜索树的后序遍历结果,通过识别根节点并递归验证左右子树的值是否满足二叉搜索树的性质。
23 3
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - II. 从上到下打印二叉树 II
本文提供了一种Python实现方法,用于层次遍历二叉树并按层打印结果,每层节点按从左到右的顺序排列,每层打印到一行。
39 3
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - I. 从上到下打印二叉树
本文介绍了使用Python实现从上到下打印二叉树的解决方案,采用层次遍历的方法,利用队列进行节点的访问。
34 2
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
51 4
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
114 2
|
22天前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
17 1