栈实现getMin
题目
实现一个特殊的栈,在实现栈的基本功能的基础上,在实现返回栈中最小元素的操作。
要求
- pop、push、getMin操作的时间复杂度都是O(1).
- 设计的栈类型可以使用现成的栈结构。
解答
在设计上我们使用两个栈,一个栈用来保存当前栈中的元素,其功能和一个正常的栈没有区别,这个栈记为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的更多相关文章
- 栈 · 有getMin功能的栈O(1)
题面 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中的最小元素的操作. 要求 pop(), push(), getMin()时间复杂度都是O(1) 思路 1.准备两个栈,数据栈+最小元素 ...
- c++后台开发面试常见知识点总结(六)算法手写
链表倒转 leetcode-206 连续子数组最大和问题(和最大的连续子序列的和) leetcode-53 输出字符串中最长的回文子串长度? leetcode-5 一个字符串,求最长无重复子串 ...
- 算法与数据结构题目的 PHP 实现:栈和队列 设计一个有 getMin 功能的栈
刚入手了一本<程序员代码面试指南>,书中题目的代码都是 Java 实现的,琢磨着把这些代码用 PHP 敲一遍,加深印象. 题目:设计一个有 getMin 功能的栈 —— 实现一个特殊的栈, ...
- 实现带有getMin的栈
题目 实现一个特殊的栈,在实现栈的基础上,再实现返回栈中最小的元素的操作. 要求 pop.push.getMin的时间复杂度是O(1) 可以使用现成的栈类型 思路 如下图所示,在栈结构中,每次pop的 ...
- 设计一个有getMin功能的栈
[说明]: 本文是左程云老师所著的<程序员面试代码指南>第一章中“设计一个有getMin功能的栈”这一题目的C++复现. 本文只包含问题描述.C++代码的实现以及简单的思路,不包含解析说明 ...
- 设计一个有getMin功能的栈(2)
题目: 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作. 要求: 1.pop.push.getMin操作的时间复杂度都是O(1) 2.设计的栈类型可以输用现成的栈结构 解答 ...
- 设计一个有getMin功能的栈(1)
题目: 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作. 要求: 1.pop.push.getMin操作的时间复杂度都是O(1) 2.设计的栈类型可以输用现成的栈结构 解答 ...
- 设计一个带有getmin功能的栈,保证时间复杂度在O(1)
2017-06-22 20:56:10 需要得到最小值,最简单的思路就是遍历一遍求出最小值.但是这样的时间复杂度会是O(n),不满足O(1)的要求.于是想到在建立一个栈来保存最小值. 具体操作是建立 ...
- 常见面试算法题JS实现-设计一个有getMin功能的栈
前言: 已经确定工作了-下周一正式入职,按理说应该是可以好好浪荡一周的,但是内心总是不安,总觉得自己这个水平真的太菜了,还是趁着现在有自己的时间,赶紧多看看书,多学习学习吧orz所以把之前校招买的书, ...
随机推荐
- C# .NET更智能的数据库操作封装项目
前面两篇文章介绍了框架的思路及里面大概的实现过程,那时候忘记上传项目,就补发一下.顺便介绍下框架使用方式,并分析下框架使用的优缺点. 先发一下前两章的链接 篇一:http://www.cnblogs. ...
- spring init
DN学院讲师招募 Markdown编辑器轻松写博文 TOP 50 CTO坐镇直招 读文章说感想获好礼 通过Spring @PostConstruct 和 @PreDestroy ...
- 基于Selenium2+Java的UI自动化(8)- 显式等待和隐式等待
一.隐式等待 package com.automation.waits; import java.util.concurrent.TimeUnit; import org.openqa.seleniu ...
- 关于使用mybatis中mapper instrances,通过session另一种操作方式
String resource = "mybatis-config.xml"; InputStream inputStream = null; try { // 获取SqlSess ...
- wemall app商城系统Android之支付宝接口RSA函数
wemall-mobile是基于WeMall的Android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享支付宝接口RSA函数,RSA签名.验签.解密等 ...
- 3893: [Usaco2014 Dec]Cow Jog
3893: [Usaco2014 Dec]Cow Jog Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 174 Solved: 87[Submit] ...
- Android:百度地图 + 百度导航
地图SDK 开发指南:http://lbsyun.baidu.com/index.php?title=androidsdk/guide/introduction 导航SDK开发指南:http://lb ...
- 面向对象的全套“企业微信”api接口的代码实现,网上太多“面向过程”微信api接口的代码,这个开源给需要的人用
有段时间没有写文章了. 一直以来,微信的热门是看得到的,很多人都需要与微信的api对接. 今天我这里就分享全套的企业微信api接口的代码. 关于微信api,网上已经有很多实现的了. 但是我今天之所以还 ...
- Oracle-操作
登录PL_SQL,输入用户名sys 密码 安装时输入的密码,选择 sysdba 打开plsqldev.exe所在目录下的PlugIns文件夹,如果没有请从其它地方拷入 打开运行命令窗口,输入命令 re ...
- SQL server 数据库(视图、事物、分离附加、备份还原))
ql Server系列:视图.事物.备份还原.分离附加 视图是数据库中的一种虚拟表,与真实的表一样,视图包含一系列带有名称的行和列数据.行和列数据用来自定义视图的查询所引用的表,并且在引用视图时动态 ...