本篇概览

  • 最近运气不错,在LeetCode上白捡一道送分题,官方设定的难度是中等,然而此题难度放在简单的题库中都是垫底的存在,对于刷题数太少的欣宸而言,这简直就是力扣的馈赠,建议大家也不要错过,花上几分钟将其拿下
  • 不唠嗑了,下面咱们一起来刷之
  • 为了提起您的兴趣,这里提前剧透一下:
  1. 用最简单的数据结构-数组,来存储数据,代码整体非常简单,适合新手阅读
  2. 执行用时执行用时3毫秒, 在所有 Java 提交中击败了100%的用户(包括官方),有下图为证

题目说明

  • 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
  • 实现 MinStack 类:
  1. MinStack() 初始化堆栈对象。
  2. void push(int val) 将元素val推入堆栈。
  3. void pop() 删除堆栈顶部的元素。
  4. int top() 获取堆栈顶部的元素。
  5. 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.
  • 提示
  1. -231 <= val <= 231 - 1
  2. pop、top 和 getMin 操作总是在 非空栈 上调用
  3. 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%
  • 接下来该我了,自己实现栈

题目分析

  • 前面废话太多,这里精简一下,说说我理解的此题的重点
  1. 数据结构:怎么存数据,才能保证高效的读写速度?
  2. 最小值问题:本题不仅要有基本的栈功能,还要时刻能返回栈内的最小值
  3. 内存怎么优化?
  4. 耗时怎么优化?
  • 接下来针对上述问题,逐个考虑

问题一:数据结构设计

  • 最高效的存取,一般是数组和链表,在java中,原始类型的数组更简单,而链表就要用到对象了,相对更复杂,所以,数组是首选,至于用数组实现后进先出的栈,那也简单嘛,用个int型变量做指针即可
  • 如下图,例如固定长度10的数组,里面存了两个有效数据,int型变量pointer等于1即可,表示数组的位置1存储着最后一个有效数据,后面再加入新的数据时,放在pointer+1的位置即可

最小值问题

  • 题目要求中规定了getMin方法要返回当前栈内的最小值,所以我们要搞清楚什么时候最小值会发生变化:
  1. 栈内增加元素时,可能新增的元素比栈内元素都小
  2. 栈内弹出元素时,可能弹出的元素是最小的那个
  • 对于增加元素时的处理最简单:准备个成员变量min,每次增加元素时,都比较增加的元素和当前min谁最小,最小的更新到min中
  • 但是,弹出时呢?最小值被弹出去了,那么原本次小的就成了最小的,但是次小的咱们没存啊,这时候有两种选择:
  1. 首先,参考官方源码,再准备一个数组,每次增加时,就把最小值放进来
  2. 其次,每次弹出时,再重新算一遍最小值,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%,内存也低于官方相关推荐

  1. Leetcode155最小栈

    题目:栈中的最小值 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈. push(x) -- 将元素 x 推入栈中. pop() -- 删除栈顶的元素. top() - ...

  2. LeetCode hot-100 简单and中等难度,51-60.

    142. 环形链表 II 难度中等570收藏分享切换为英文关注反馈 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整数 pos 来表示 ...

  3. 【Java】Leetcode155 最小栈 (运用数据结构:栈 解题)

    题目: 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈. push(x) -- 将元素 x 推入栈中. pop() -- 删除栈顶的元素. top() -- 获取 ...

  4. LeetCode hot-100 简单and中等难度,61-70.

    207. 课程表 难度中等520 你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 . 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成 ...

  5. LeetCode hot-100 简单and中等难度,81-90.

    打家劫舍系列题 198. 打家劫舍 难度简单1005收藏分享切换为英文关注反馈 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防 ...

  6. LeetCode hot-100 简单and中等难度,31-40.

    75. 颜色分类 难度中等527收藏分享切换为英文关注反馈 给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中, ...

  7. LeetCode hot-100 简单and中等难度,21-30.

    46. 全排列 难度中等829 给定一个 没有重复 数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3 ...

  8. LeetCode hot-100 简单and中等难度,71-80.

    279. 完全平方数 难度中等538收藏分享切换为英文关注反馈 给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n.你需要让组成和的完全平方数的个数最少 ...

  9. LeetCode hot-100 简单and中等难度,91-100.

    461. 汉明距离 难度简单307收藏分享切换为英文关注反馈 两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目. 给出两个整数 x 和 y,计算它们之间的汉明距离. 注意: 0 ≤ ...

最新文章

  1. eclipse 源码设置UTF-8 (eclipse可以为JSP HTML 等各种文件不同编码格式设置) 在windows - preference- general-workspace
  2. org.springframework.data.mapping.PropertyReferenceException: No property xxxx found for type Xxxx
  3. cout的输出格式初探
  4. 如何优化增强第三方库?
  5. 构建可扩展的有状态服务
  6. 【JVM】通过javap命令分析Java汇编指令
  7. abb机器人searchl报错_西门子PLC1200与ABB机器人通信
  8. Linux内存管理:分页机制
  9. python中文文本处理_python简单文本处理的方法
  10. 关于ashx的基本应用
  11. kafak 命令使用
  12. 微信小程序报Cannot read property ‘setData‘ of undefined的错误
  13. php隐藏json数据,PHP调用出json后出来的数目字 想隐藏掉 50份求高手帮忙下
  14. 连接 mysql 数据库失败频繁的原因探秘
  15. 公式编辑器如何打出空格
  16. 三菱伺服驱动器MR-JE CN3号串口线连接
  17. .net EF 新手教程
  18. 在项目中遇到导入TXT乱码现象。为什么UTF-8不行?ANSI是什么编码?
  19. DC的逻辑综合与优化
  20. IFS认证咨询,关于家用和个人护理产品安全和质量的发展和评估项目

热门文章

  1. webstorm报错:TS2307: Cannot find module ‘./App.vue‘ or its corresponding type declarations
  2. 典型相关分析,奇异值分解,RRR(Reduced-Rank Regression)
  3. Linux常用指令学习(篇三):文件搜索命令
  4. 3月份安全软件品牌报告 金山、360负面缠身
  5. layui tabl 工具栏按钮双击事件
  6. java.lang.IllegalArgument.Exception:Malformed
  7. 电动机额定电流快速估算
  8. PC端 Rockchip RKNN-Toolkit 连接 Rockchip NPU 设备
  9. Fail to load response data :No content available for preflight request 加载响应数据失败:请求没有可用内容
  10. Federation 简介