题目

实现一个特殊的栈,在实现栈的基本功能的基础上,在实现返回栈中最小元素的操作。

要求

  1. pop、push、getMin操作的时间复杂度都是O(1).
  2. 设计的栈类型可以使用现成的栈结构。

解答

在设计上我们使用两个栈,一个栈用来保存当前栈中的元素,其功能和一个正常的栈没有区别,这个栈记为stackData;另一个栈用于保存每一步的最小值,这个栈记为stackMin。具体实现的方式有两种。

第一种

压入数据规则

假设当前数据为newNum,现将其压入stackData。然后判断stackMin是否为空:

  • 如果为空,则newNum也压入stackMin。
  • 如果不为空,则比较newNum和stackMin的栈顶元素中哪一个更小:
  • 如果newNum更小或两者相等,则newNum也压入stackMin;
  • 如果stackMin中的栈顶元素小,则stackMin不压如任何内容。

举例:一次压入3、4、5、1、2、1的过程中,stackData和stackMin的变化下图:

数据弹出规则

  先在stackData中弹出栈顶元素,记为value。然后比较当前stackMin的栈顶元素和value哪一个更小。

  通过上文提到的压入规则可知,stackMin中存在的元素是从栈底到栈顶逐渐变小的,stackMin栈顶的元素既是stackMin栈的最小值,也是当前stackData栈中的最小值。所以不会出现value比stackMin的栈顶元素更小的情况,value只可能大于或等于stackMin的栈顶的元素。

  当value等于stackMin的栈顶元素时,stackMin弹出栈顶元素;当value大于stackMin的栈顶元素时,stackMin不弹出栈顶元素;返回false。

  很显然可以看出,压入与弹出规则是对应的。

查询当前栈中的最小值操作

  由上文的压入数据规则和弹出数据规则可知,stackMin始终记录着stackData中的最小值,所以,stackMin栈顶元素始终是当前stackData中的最小值。

下面看一下代码:

public class MyStack1 {

    private Stack<Integer> stackData;
private Stack<Integer> stackMin; public MyStack1(){
stackData = new Stack<>();
stackMin = new Stack<>();
} public void push(int newNum){
if(this.stackMin.isEmpty()){
this.stackMin.push(newNum);
}else if(newNum<=this.getMin()){
this.stackMin.push(newNum);
}
this.stackData.push(newNum);
} public int pop(){
if(this.stackData.isEmpty()){
throw new RuntimeException("Your stack is empty.");
}
int value = this.stackData.pop();
if(value==this.getMin()){
this.stackMin.pop();
}
return value;
} public int getMin(){
if(this.stackMin.isEmpty()){
throw new RuntimeException("Your stack is empty");
}
return this.stackMin.peek();
}
}

第二种

压入数据的规则

假设当前数据为newNum,现将其压入stackData、然后判断stackMin是否为空。

如果为空,则newNum也压入stackMin;如果不为空,则比较newNum和stackMin的栈顶元素中哪一个更小;

如果newNum更小或者两者相等,则newNum也压入stackMin;如果stackMin中栈顶元素小,则吧stackMin的栈顶元素重复压入stackMin,即在栈顶元素上再压入一个栈顶元素。

举例:一次压入3、4、5、1、2、1的过程,stackData和stackMin的变化如下图。

弹出数据规则

在stackData中弹出数据,弹出数据记为value;弹出stackMin中的栈顶;返回value。很明显可以看出,压入与弹出规则是对应的。

查询当前栈中的最小值操作

由上文的压入数据规则和弹出数据规则可知,stackMin始终记录着stackData中的最小值,所以stackMin的栈顶元素始终是当前stackData中的最小值。

方案二的代码实现如MyStack2类所示:

public class MyStack2 {
private Stack<Integer> stackData;
private Stack<Integer> stackMin; public MyStack2(){
stackData = new Stack<>();
stackMin = new Stack<>();
} public void push(int newNum){
if(this.stackMin.isEmpty()){
this.stackMin.push(newNum);
}else if(newNum<this.getMin()){
this.stackMin.push(newNum);
}else{
int newMin = this.stackMin.peek();
this.stackMin.push(newMin);
}
this.stackData.push(newNum);
} public int pop(){
if(this.stackData.isEmpty()){
throw new RuntimeException("Your stack is empty.");
}
this.stackMin.pop(); return this.stackData.pop();
} public int getMin(){
if(this.stackMin.isEmpty()){
throw new RuntimeException("Your stack is empty");
}
return this.stackMin.peek();
}
}

方案一和方案二其实都是stackMin栈保存着stackData每一步的最小值。共同是所有操作的时间复杂度都为O(1)、空间复杂度都是O(n)。区别是:方案一种stackMin压入时稍省空间,但是弹出操作稍费时间;方案二中stackMin压入时稍费空间,但是弹出操作稍省时间。

栈实现getMin的更多相关文章

  1. 栈 · 有getMin功能的栈O(1)

    题面 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中的最小元素的操作. 要求 pop(), push(), getMin()时间复杂度都是O(1) 思路 1.准备两个栈,数据栈+最小元素 ...

  2. c++后台开发面试常见知识点总结(六)算法手写

    链表倒转  leetcode-206 连续子数组最大和问题(和最大的连续子序列的和)   leetcode-53 输出字符串中最长的回文子串长度?  leetcode-5 一个字符串,求最长无重复子串 ...

  3. 算法与数据结构题目的 PHP 实现:栈和队列 设计一个有 getMin 功能的栈

    刚入手了一本<程序员代码面试指南>,书中题目的代码都是 Java 实现的,琢磨着把这些代码用 PHP 敲一遍,加深印象. 题目:设计一个有 getMin 功能的栈 —— 实现一个特殊的栈, ...

  4. 实现带有getMin的栈

    题目 实现一个特殊的栈,在实现栈的基础上,再实现返回栈中最小的元素的操作. 要求 pop.push.getMin的时间复杂度是O(1) 可以使用现成的栈类型 思路 如下图所示,在栈结构中,每次pop的 ...

  5. 设计一个有getMin功能的栈

    [说明]: 本文是左程云老师所著的<程序员面试代码指南>第一章中“设计一个有getMin功能的栈”这一题目的C++复现. 本文只包含问题描述.C++代码的实现以及简单的思路,不包含解析说明 ...

  6. 设计一个有getMin功能的栈(2)

    题目: 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作. 要求: 1.pop.push.getMin操作的时间复杂度都是O(1) 2.设计的栈类型可以输用现成的栈结构 解答 ...

  7. 设计一个有getMin功能的栈(1)

    题目: 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作. 要求: 1.pop.push.getMin操作的时间复杂度都是O(1) 2.设计的栈类型可以输用现成的栈结构 解答 ...

  8. 设计一个带有getmin功能的栈,保证时间复杂度在O(1)

    2017-06-22  20:56:10 需要得到最小值,最简单的思路就是遍历一遍求出最小值.但是这样的时间复杂度会是O(n),不满足O(1)的要求.于是想到在建立一个栈来保存最小值. 具体操作是建立 ...

  9. 常见面试算法题JS实现-设计一个有getMin功能的栈

    前言: 已经确定工作了-下周一正式入职,按理说应该是可以好好浪荡一周的,但是内心总是不安,总觉得自己这个水平真的太菜了,还是趁着现在有自己的时间,赶紧多看看书,多学习学习吧orz所以把之前校招买的书, ...

随机推荐

  1. redis的数据类型 (一) 字符串

    redis中存储方式是以键值对存储的,所以叫做字典试.redis(Remote dictionary server)远程字典服务器 每个redis数据类型,都会有增加.删除,查看的功能,用实例来学习命 ...

  2. R语言入门(二)基础语法

    1.help可以提供帮助,如help(nchar), help("[["),或者用?nchar也能获取帮助.example(nchar)可以获取到某个主题的使用方法. 2.ncha ...

  3. 微信小程序之提高应用速度小技巧

    作者:vicyao, 腾讯web前端开发 高级工程师商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/294.htm ...

  4. WebGIS中自定义互联网地图局部注记的一种方案

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.    前言 实际项目中我们经常会遇到这样一种场景:地图底图可能是互 ...

  5. css样式表1 2017-03-11

    样式表 DIV + CSS 一.        样式表的分类 以下均以div标签为例,可以换成其他标签 1.  内联样式表 格式: style="属性1:属性值1:属性2:属性值2:属性3: ...

  6. gulp折腾日记——gulp-livereload

    大家好,虽然在博客园注册了很长一段时间,但我还没在博客园写过博客,这是在博客园的第一篇博客,希望能养成每周写博客的好习惯 O(∩∩)O~~) 今天要聊得是gulp的一个实时刷新的插件gulp-live ...

  7. Spring+SpringMVC+MyBatis+easyUI整合基础篇(九)版本控制

    日常啰嗦 还好在第一篇文章里就列好了接下来的主线及要写的知识点,不然都不知道要写什么东西了,开篇里已经列了基础篇要讲svn和git的知识点,所以这一篇就写一下版本控制. 项目实际效果展示在这里,账密: ...

  8. Postgresql 经纬度

    增加一列: add column `location` geometry default p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px &q ...

  9. 【转载】扩展Robot Framework,实现失败用例自动再执行(失败重跑)

    使用自动化脚本进行测试,经常受环境影响等各方面导致本能成功的脚本失败,下面介绍了RFS框架下,失败重跑的方法: 通过改写RobotFramework源代码增加--retry选项,实现test级别的失败 ...

  10. 微信iOS客户端升级内核对自定义分享的影响

    上周,业务同学反应,公司的商品详情页,在有的Iphone手机上自定义分享信息失效.在自己手机上一直无法重现,在一个同事的手机上也重现了. 后来看到<微信iOS客户端将升级为WKWebview内核 ...