LeetCode155:最小栈,最简单的中等难度题,时间击败100%,内存也低于官方
欢迎访问我的GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本篇概览
- 最近运气不错,在LeetCode上白捡一道送分题,官方设定的难度是中等,然而此题难度放在简单的题库中都是垫底的存在,对于刷题数太少的欣宸而言,这简直就是力扣的馈赠,建议大家也不要错过,花上几分钟将其拿下
- 不唠嗑了,下面咱们一起来刷之
- 为了提起您的兴趣,这里提前剧透一下:
- 用最简单的数据结构-数组,来存储数据,代码整体非常简单,适合新手阅读
- 执行用时执行用时3毫秒, 在所有 Java 提交中击败了100%的用户(包括官方),有下图为证

题目说明
- 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
- 实现 MinStack 类:
- MinStack() 初始化堆栈对象。
- void push(int val) 将元素val推入堆栈。
- void pop() 删除堆栈顶部的元素。
- int top() 获取堆栈顶部的元素。
- int getMin() 获取堆栈中的最小元素。
- 示例1
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
- 提示
- -231 <= val <= 231 - 1
- pop、top 和 getMin 操作总是在 非空栈 上调用
- push, pop, top, and getMin最多被调用 30000 次
官方解法
- 先来看官方解法,简单的说,就是用JDK已有的栈对象Deque来完成push、pop、top等操作,如下所示
class MinStack {
Deque<Integer> xStack;
Deque<Integer> minStack;
public MinStack() {
xStack = new LinkedList<Integer>();
minStack = new LinkedList<Integer>();
minStack.push(Integer.MAX_VALUE);
}
public void push(int x) {
xStack.push(x);
minStack.push(Math.min(minStack.peek(), x));
}
public void pop() {
xStack.pop();
minStack.pop();
}
public int top() {
return xStack.peek();
}
public int getMin() {
return minStack.peek();
}
}
- 读完这段代码我就茫然了:我来LeetCode刷题是为了什么?为了学习Deque类的API使用方法吗?
- 不,我是来学习和提升自己的算法能力的,这种API调用并不是我心目中的答案,官方找不到,我就自己动手
- 毕竟,实现个栈能有多大难度?
- 为了弄清楚自己和官方的差距,我先将上述官方源码提交一次,看看成绩如何,如下图,官方在使用Deque类的情况下,执行用时击败93%,内存消耗击败57%

- 接下来该我了,自己实现栈
题目分析
- 前面废话太多,这里精简一下,说说我理解的此题的重点
- 数据结构:怎么存数据,才能保证高效的读写速度?
- 最小值问题:本题不仅要有基本的栈功能,还要时刻能返回栈内的最小值
- 内存怎么优化?
- 耗时怎么优化?
- 接下来针对上述问题,逐个考虑
问题一:数据结构设计
- 最高效的存取,一般是数组和链表,在java中,原始类型的数组更简单,而链表就要用到对象了,相对更复杂,所以,数组是首选,至于用数组实现后进先出的栈,那也简单嘛,用个int型变量做指针即可
- 如下图,例如固定长度10的数组,里面存了两个有效数据,int型变量pointer等于1即可,表示数组的位置1存储着最后一个有效数据,后面再加入新的数据时,放在pointer+1的位置即可

最小值问题
- 题目要求中规定了getMin方法要返回当前栈内的最小值,所以我们要搞清楚什么时候最小值会发生变化:
- 栈内增加元素时,可能新增的元素比栈内元素都小
- 栈内弹出元素时,可能弹出的元素是最小的那个
- 对于增加元素时的处理最简单:准备个成员变量min,每次增加元素时,都比较增加的元素和当前min谁最小,最小的更新到min中
- 但是,弹出时呢?最小值被弹出去了,那么原本次小的就成了最小的,但是次小的咱们没存啊,这时候有两种选择:
- 首先,参考官方源码,再准备一个数组,每次增加时,就把最小值放进来
- 其次,每次弹出时,再重新算一遍最小值,O(n)的耗时,感觉还好...
- 斟酌再三,方案一会导致内存翻倍,所以还是优先考虑方案二吧,也就是每次弹出时重新计算一遍最小值
内存怎么优化?
- 接下来要考虑如何少使用内存
- 首先要搞清楚的是:准备多大的数组才能满足题目要求,官方说明如下图,注意红色箭头,如果调用三万次push,那就说明会存三万个int数字,所以数组长度如果低于三万,提交后就可能报错,达不到官方要求

- 所以,数组的长度固定是三万吗?
- 当然不需要,提交代码后,LeetCode会执行多个用例,不可能每个用例都push三万次的,所以固定三万的长度,看似保险,实则浪费
- 所以,优化思路可以借鉴HashMap的源码:存不下的时候,就扩容,也就是准备一个新数组,把老数组的数据复制进去,至于扩多少?逻辑不必太复杂,翻倍即可
耗时怎么优化
- 还有最后一个问题要考虑:时间还能优化吗?
- 要想优化时间,首先咱们要知道哪里会耗时,回顾前面的设计,最耗时的地方应该是弹出元素的时候,这时候要重新计算最小值,时间复杂度是O(n),每次弹出都要执行,有没有可能优化一下呢?
- 考虑下图这种情况,栈内数据是1、2、3,其中1在栈顶,那么弹出1之后,自然要在2和3中寻找最小值作为栈的最小值了,这是必要操作,不能优化

- 但是下图这种情况呢?3在栈顶,弹出去之后,1还是最小值,此时就没有必要重新比较一遍了

- 好了,分析和设计都完成了,也该写代码验证效果了,我有种预感,自己设计的栈,比LeetCode官方的更快,也更省内存,希望不要被现实打脸...
编码
- 完整代码如下,有了前面的详细分析,相信您可以轻松看懂,注意我这里数组的初始长度是64,您也可以调整成其他值试试
class MinStack {
private int[] array = new int[64];
private int pointer = -1;
private int min = Integer.MAX_VALUE;
public MinStack() {
}
public void push(int val) {
array[++pointer] = val;
min = Math.min(min, val);
// 扩容
if (pointer==(array.length-1)) {
int[] temp = new int[array.length*2];
System.arraycopy(array, 0, temp, 0, array.length);
array = temp;
}
}
public void pop() {
pointer--;
// 这里可以优化:如果弹出的不是最小值,那就没必要重算呀!
if (array[pointer+1]==min) {
min = Integer.MAX_VALUE;
for (int i=0;i<=pointer;i++) {
min = Math.min(min, array[i]);
}
}
}
public int top() {
return array[pointer];
}
public int getMin() {
return min;
}
}
- 提交,顺利AC,成绩如下,用时和内存双双优于官方,尤其是用时,击败百分百!

- 至此,第155题顺利完成,自我感觉是有一些收获的,至少比官方的面向API编程收获更大,更何况成绩比官方的还好一些...
欢迎关注博客园:程序员欣宸
LeetCode155:最小栈,最简单的中等难度题,时间击败100%,内存也低于官方的更多相关文章
- Leetcode题目155.最小栈(简单)
题目描述: 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈. push(x) -- 将元素 x 推入栈中.pop() -- 删除栈顶的元素.top() -- 获取栈顶 ...
- [Swift]LeetCode155. 最小栈 | Min Stack
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...
- LeetCode155.最小栈
设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈. push(x) -- 将元素 x 推入栈中. pop() -- 删除栈顶的元素. top() -- 获取栈顶元素. ...
- 力扣1689. 十-二进制数的最少数目-C语言实现-中等难度题
题目 传送门 如果一个十进制数字不含任何前导零,且每一位上的数字不是 0 就是 1 ,那么该数字就是一个 十-二进制数 .例如,101 和 1100 都是 十-二进制数,而 112 和 3001 不是 ...
- lintcode 中等题:Min stack 最小栈
题目 带最小值操作的栈 实现一个带有取最小值min方法的栈,min方法将返回当前栈中的最小值. 你实现的栈将支持push,pop 和 min 操作,所有操作要求都在O(1)时间内完成. 解题 可以定义 ...
- LeetCode之Min Stack 实现最小栈
LeetCode相关的网上资源比较多,看到题目一定要自己做一遍,然后去学习参考其他的解法. 链接: https://oj.leetcode.com/problems/min-stack/ 题目描述: ...
- LeetCode 腾讯精选50题--最小栈
题目很简单,实现一个最小栈,能够以线形的时间获取栈中元素的最小值 自己的思路如下: 利用数组,以及两个变量, last用于记录栈顶元素的位置,min用于记录栈中元素的最小值: 每一次push,都比较m ...
- [LeetCode] Min Stack 最小栈
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...
- [CareerCup] 3.2 Min Stack 最小栈
3.2 How would you design a stack which, in addition to push and pop, also has a function min which r ...
- UVA442 Matrix Chain Multiplication 矩阵运算量计算(栈的简单应用)
栈的练习,如此水题竟然做了两个小时... 题意:给出矩阵大小和矩阵的运算顺序,判断能否相乘并求运算量. 我的算法很简单:比如(((((DE)F)G)H)I),遇到 (就cnt累计加一,字母入栈,遇到) ...
随机推荐
- 使用android studio发布android与flutter混合开发项目
一.生成androd签名证书 Android studio的Build > Grenerate Signed Bundle 选择apk 点击Create New 录入对应的签名信息:点击确定 对 ...
- Sublime Text Windows/Linux平台快捷键
编辑 按键 对应命令 Ctrl + X 删除行 Ctrl + 行后插入 Ctrl + ⇧ + 行前插入 Ctrl + ⇧ + ↑ 上移文本/选择 Ctrl + ⇧ + ↓ 下移文本/选择 Ctrl + ...
- 有管django使用orm 字段报错问题
直接删除表,重新生成,首先删除:migrations 中,上传记录,然后django_migrations,
- 【Haxe】(一)VSCode 搭建 Haxe 开发环境
前言 咱换工作啦! 新工作这边需要用到的开发语言是 Haxe,最近大概会写几篇笔记.Haxe 的介绍就不写了,打算记录点有用的学习内容,先从搭建开发环境开始吧! 当前适用版本: VSCode:Curr ...
- Java的运算符和表达式(基础语法学习)
一.运算符 在Java中用于程序计算的操作符统称为运算符,运算符分为如下几类 1.算数运算符 运算符 说明 + 加号两边是数值,可以运算,如果一边存在字符串,则当作连接符 a+b - 两个数相加, ...
- VS code 的安装
VS code 的安装 Win10环境配置(一)--C\C++篇 Win10环境配置(二) --Java篇 安装前先 ,完成环境的配置 1.工具准备 官网下载:Visual Studio Code 2 ...
- Profinet转EtherNet/IP网关连接AB PLC的应用案例
西门子S7-1500 PLC(profinet)与AB PLC以太网通讯(EtherNet/IP).本文主要介绍捷米特JM-EIP-PN的Profinet转EtherNet/IP网关,连接西门子S7- ...
- n皇后问题的分析和实现
N皇后问题的分析和实现 1.实现要求 2.代码实现 1.实现要求 在n*n的方格棋中,放置n个皇后,要求每个皇后不同行,不同列,不同对角线 以行为依据,遍历行,判断行对应的列是否符合要求 判定要求: ...
- 2023年郑州轻工业大学校赛邀请赛jc
比赛时,jxh和myh从头开始看题,我拿着试题册去找签到,很快他们签上了一个数学题,我跟他们说兔子和飞镖可以写,刚开始飞镖这个题我先wa了一次,因为刚开始的思路少考虑了情况,我们队后来改的挺乱,jxh ...
- java文件共享实现方案
写在前面,由于项目要求负载,又不想大动干戈采用比较贵的设备和高大上的框架,经过一番研究,想使用文件共享方式实现文件的跨服务器访问.本方案采用了jcifs和smbj框架,若想用,请自行查找资源.此为初步 ...