后面咱们学习了很多对于栈的常识,比方《动图演示:手撸堆栈的两种实现办法!》和《JDK 居然是这样实现栈的?》,那么接下来咱们再来刷一些对于栈的经典面试题以坚固学过的常识。

咱们明天的面试题是这样的…

题目

定义栈的数据结构,请在该类型中实现一个可能失去栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的工夫复杂度都是 O(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.

LeetCode 地址:https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/

思考

首先来说这道题目自身很好了解,它的实现难点在于以下两个方面:

当咱们进行 pop(移除栈顶元素)操作时如果删除的是以后最小值,那么咱们如何寻找下一个最小值?

要保障调用 min、push 及 pop 的工夫复杂度都是 O(1)。

也就是说,在咱们执行了 pop 时如果移除的栈中最小的值,那么如何寻找栈中的下一个最小元素?并且要保障操作的工夫复杂度为 O(1)。这个工夫复杂度制约了咱们在移除了最小值之后不能通过遍历查找下一个最小值,所以这就成为了这道题的难点。

比方当咱们移除以下栈顶元素值:

因为最小值就是 1,因而在移除之后最小值也被移除了,如下图所示:

那么接下来,让咱们一起思考 3 分钟,想一想应该如何解决这个问题~

解题思路

其实咱们能够在每次入栈时,判断以后元素是否小于最小值,如果小于则将原最小值和最新的最小值相继入栈,这样在调用 pop 时即便移除的是最小值,咱们也能通过获取下一个元素失去一个新的最小值,执行流程如下所示。

操作步骤1

入栈第一个元素,因为是第一个元素,因而最小值就是此元素的值。

操作步骤2

入栈第二个元素,如下图所示:

因为入栈的元素 3 比 8 小,所以先将栈中的原最小值 8 存入栈中,再将 3 入栈。

操作步骤3

入栈第三个元素,如下图所示:

因为入栈元素 5 大于 3,因而栈中的最小值不变,间接将元素 5 入栈。

操作步骤4

持续入栈,如下图所示:

入栈元素 1 小于 3,因而先将原最小值 3 入栈,再将 1 入栈,栈中的最小值更改为 1。

操作步骤5

执行出栈操作,如下图所示:

元素 1 出栈,判断以后元素就是栈的最小值,因而将栈顶元素 3 设置为最小值,并移除元素 3,如下图所示:

操作步骤6

持续出栈,如下图所示:

因为元素 5 不是以后最小值,因而间接出栈。

操作步骤7

持续出栈,如下图所示:

因为出栈元素 3 为最小值,因而持续将最小值设置为栈顶元素 8,并将栈顶元素出栈,如下图所示:

这样就剩下最初一个元素了,最初一个元素出栈之后就成空栈了,整个流程就执行完了。

实现代码1

接下来咱们将下面的思路用代码实现一下,咱们用数组实现的栈来实现相干的性能,代码如下:

class MinStack {

private int[] data; // 栈数据

private int maxSize; // 最大长度

private int top; // 栈顶指针(下标)

private int min; // 最小值

// 构造函数

public MinStack() {

// 设置默认值

maxSize = 10000;

data = new int[maxSize];

top = -1;

min = Integer.MAX_VALUE;

}

// 入栈(增加元素)

public void push(int x) {

if (min >= x) {

// 遇到了更小的值,记录原最小值(入栈)

data[++top] = min;

min = x;

}

// 以后值入栈

data[++top] = x;

}

// 出栈(移除栈顶元素)

public void pop() {

if (min == data[top]) {

min = data[--top]; // 拿到原最小值,并(将原最小值)出栈

}

--top; // 出栈

}

// 查找栈顶元素

public int top() {

return data[top];

}

// 查问最小值

public int min() {

return min;

}

}

上述代码在 LeetCode 的执行后果如下:

能够看出性能还是很高的,超过了 99.92% 的用户,内存耗费也不大。它的外围代码在 push 办法内,先将原最小值和最新最小值相继入栈,在 pop 出栈时判断出栈元素是否为最小值,如果是最小值则将以后最小值指向栈顶元素并将栈顶元素出栈,这样就失去了下一个新的最小值了。

实现代码2

如果咱们不想应用数组的自定义栈来实现,还能够应用 Java 中自带的栈 Stack 来实现此性能,代码如下:

class MinStack {

private Stack stack = new Stack<>();

private int min = Integer.MAX_VALUE;

public MinStack() { }

// 入栈(增加元素)

public void push(int x) {

if (x <= min) {

// 遇到了更小的值,记录原最小值(入栈)

stack.push(min);

min = x;

}

stack.push(x);

}

// 出栈(移除栈顶元素)

public void pop() {

if (stack.pop() == min) {

min = stack.pop(); // 取出原最小值

}

}

// 查找栈顶元素

public int top() {

return stack.peek();

}

// 查问最小值

public int min() {

return min;

}

}

上述代码在 LeetCode 的执行后果如下:

从后果能够看出,应用 Java 中自带的栈的性能不如自定义数组的栈,但代码还是通过了测试。这种实现形式的长处就是代码比较简单,能够利用了 Java 本身的 API 来实现了最小值的查找。

这种实现代码的形式(应用 Java API),在刷题或者理论面试中如果没有非凡阐明是能够间接用的。

总结

本文咱们通过两种形式:自定义数组栈和 Java API 中的 Stack 来实现了栈中最小值的性能,保障了在调用栈的 min、push 及 pop 办法时的工夫复杂度都是 O(1)。两种实现形式的代码尽管略不雷同,但实现思路都是一样的,都是在元素入栈时判断以后元素是否小于最小元素,如果小于最小元素则先将原最小值入栈,再将以后最小元素入栈,这样当调用 pop 办法时,即便移除的是最小值,只须要将下一个元素取出即为新的最小值了,这样就能够实现调用 min、push 及 pop 办法时的工夫复杂度都是 O(1) 了。

最初

机智的你肯定还有其余的实现答案,评论区通知我吧~

原创不易,各位素质四连,谢啦。

文末福利:搜寻公众号「Java中文社群」发送“面试”,支付最新的面试材料。

java栈最小值的实现,关于java:算法图解如何找出栈中的最小值相关推荐

  1. 【算法14】找出数组中两个只出现一次的数字

    [题 目]一个整型数组中除了两个数字外,其他的数字都出现两次.请找出这两个只在数组中出现一次的数字.要求时间复杂度O(n),空间复杂度O(1). [思 路]首先我们考虑一个稍微简单点的情况:如果这个数 ...

  2. 小小c#算法题 - 1 - 找出数组中满足条件的两个数

    把一些东西放到网上,看的时候方便一些.代码可能有bug且不是最佳解决方案,仅供参考. 题目:输入一个按升序排序的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字. 要求时间复杂度是 ...

  3. 滑动窗口算法思想,找出字符串中的所有字母异位词

    力扣大神写的诗 一开始不理解滑动窗口是什么! 看完此诗我才明白,滑动窗口其实就是双指针的一种形式 左右指针齐头进. c#代码如下 public class Solution {public IList ...

  4. 算法图解:如何找出栈中的最小值?

    作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 前面我们学习了很多关于栈的知识,比如<动图演示:手撸堆栈的两种实现方法!&g ...

  5. java 算法之找出数组中第二大的数

    1.如果仅考虑实现功能而不考虑效率,可以先通过排序算法将数组排序,然后根据数组下标来访问数组中第二大的数,,最快的排序算法一般为快速排序算法,但是其时间复杂度为(nlogn),根据下标访问需要便利一遍 ...

  6. java数组出现次数最多的数_找出数组中出现次数最多的那个数——主元素问题...

    方法一:以空间换时间,可以定义一个计数数组int count[101],用来对数组中数字出现的次数进行计数(只能针对数组中数字的范围1~100),count数组中最大的元素对应的下标,即为出现次数最多 ...

  7. java如何找重复数字_Java如何找出数组中重复的数字

    题目描述:找出数组中重复的数字,具体内容如下 在一个长度为n的数组里的所有数字都在 0~n-1的范围内.数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复了几次.请找出数组中任意 ...

  8. 数据结构第5章例题 若矩阵Am×n中存在某个元素aij满足:aij是第i行中的最小值且是第j列中的最大值,则称该元素为矩阵A的一个鞍点。试编写一个算法,找出A中的所有鞍点。

    [例5.1] 若矩阵Am×n中存在某个元素aij满足:aij是第i行中的最小值且是第j列中的最大值,则称该元素为矩阵A的一个鞍点.试编写一个算法,找出A中的所有鞍点. 算法如下: void saddl ...

  9. java 数组不重复_java如何找出数组中的不重复数字

    找出数组中不重复的一个数字,题目大致是这样的:int[] a = { 1, 2, 3, 4, 3, 2, 1 }; 在线视频教程推荐:java在线学习 解决办法是:public static int ...

最新文章

  1. 一本真正讲“大数据”处理思路的书
  2. tableau必知必会之通过服务器视图的全屏实现多媒体展示
  3. hive解决数据倾斜问题_Hive数据倾斜和解决办法
  4. PHP上传文件大小限制的问题(转)
  5. Bootstrap-组件-3
  6. [国嵌笔记][025][ARM指令分类学习]
  7. Winform里面的缓存,MemoryCache使用
  8. linux搭建博客-day 7安装Nginx
  9. Fashion Your Firefox
  10. Django开发教程 第一节 HelloWorld
  11. tbpbebzbyb英文_化工常用英文缩写
  12. Python爬取房天下二手房信息
  13. 数据分析——常见数据指标汇总
  14. 【craps赌博游戏】
  15. mw320r虚拟服务器,水星MW320R路由器桥接设置教程-水星路由器设置
  16. cadence 画电路图时出现绿色的倒三角
  17. 数据压缩算法之zigZag--一种对负数友好的编码(2000多字总结)
  18. Foxmail客户端添加163账号和邮件备份163邮箱
  19. 哈理工oj 1073 病毒
  20. BP或FI12维护银行账户,报错“银行帐户编号XXX必须具有长度 18”

热门文章

  1. mysql并发量_高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!
  2. excel数据库_EXCEL建立简单数据库,使用VLOOKUP调用(单元格联动)
  3. 侍魂胧月传说显示服务器未开启,侍魂胧月传说打开游戏黑屏怎么办 黑屏相关问题解答...
  4. 苹果CMS V10 播放记录_苹果cms10怎么更新集数?
  5. matlab中fitrsvm函数,训练用于一类和二类分类的支持向量机 (SVM) 分类器
  6. 关于cmd如何进出文件夹
  7. HNU 程序设计课 函数公式题
  8. 利用python进行数据分析——第13章 python建模库介绍
  9. 利用python进行数据分析——第11章时间序列
  10. 2018网易在线笔试题