01_设计一个有getMin功能的栈
01_设计一个有getMin功能的栈
【题目】
实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
【要求】
- pop、push、getMin操作的时间复杂度都是O(1)
- 设计的栈类型可以使用现成的栈结构
方法一:
【思路】我们使用两个栈,一个栈用来保存当前栈中的元素,其功能和一个正常的栈没有区别,这个栈记为 stackData;另一个栈用于保存每一步的最小值,这个栈记为 stackMin。具 体的实现方式有两种
(1)压入数据规则
假设当前数据为newNum,先将其压入stackData。然后判断 stackMin 是否为空:
- 如果为空,则 newNum 也压入 stackMin。
- 如果不为空,则比较 newNum 和 stackMin 的栈顶元素中哪一个更小;
- 如果 newNum 更小或两者相等,则 newNum 也压入 stackMin;
- 如果 stackMin 中栈顶元素小,则 stackMin 不压入任何内容。
(2)弹出数据规则 先在 stackData 中弹出栈顶元素,记为 value。然后比较当前 stackMin 的栈顶元素和 value 哪一个更小。 通过上文提到的压入规则可知,stackMin 中存在的元素是从栈底到栈顶逐渐变小的, stackMin 栈顶的元素既是 stackMin 栈的最小值,也是当前 stackData 栈的最小值。所以不会出现 value 比 stackMin 的栈顶元素更小的情况,value 只可能大于或等于 stackMin 的栈顶元素。 当 value 等于 stackMin 的栈顶元素时,stackMin 弹出栈顶元素;当 value 大于 stackMin 的栈 顶元素时,stackMin 不弹出栈顶元素,返回 value。 很明显可以看出,压入与弹出规则是对应的。
(3)查询当前栈中的最小值操作 由上文的压入数据规则和弹出数据规则可知,stackMin 始终记录着 stackData 中的最小值。 所以,stackMin 的栈顶元素始终是当前 stackData 中的最小值。
方案一的代码实现如 MyStack1 类所示:
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import java.util.Stack;
/**
* 1、设计一个有getMin功能的栈
*
* 【题目】
*
* 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
*
* 【要求】
*
* 1. pop、push、getMin操作的时间复杂度都是O(1)
* 2. 设计的栈类型可以使用线成的栈结构
*/
public class MyStack1 {
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public MyStack1() {
this.stackData = new Stack<Integer>();
this.stackMin = new Stack<Integer>();
}
//压栈
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("栈中元素为空!");
}
int value = this.stackData.pop();
if (value == this.getMin()) {
this.stackMin.pop();
}
return value;
}
private int getMin() {
if (this.stackMin.isEmpty()) {
throw new RuntimeException("栈中元素为空!");
}
// Java利用Stack类的peek()函数获取堆栈中的顶部元素
return this.stackMin.peek();
}
}
本题对应于leetcode
对应于leetcode上的实现方式如下:
class MinStack {
Stack<Integer> stackData;
Stack<Integer> stackMin;
public MinStack() {
this.stackData = new Stack();
this.stackMin = new Stack();
}
// 将val元素压入栈
public void push(int val) {
// 1.1 存放最小值的栈stackMin是否为空,若为空则将当前元素压入栈
// 1.2 判断当前stackMin栈的栈顶元素与val大小,若当前val更小,则压入栈
if(stackMin.isEmpty() || stackMin.peek() >= val) {
stackMin.push(val);
}
stackData.push(val);
}
//删除堆栈栈顶元素
public void pop() {
// 这里stackMin出栈的情况主要是当stackData出栈的元素是栈最小值元素的情形
if (stackData.pop().equals(stackMin.peek())) {
this.stackMin.pop();
}
}
//获取堆栈顶部的元素
public int top() {
return this.stackData.peek();
}
// 获取堆栈的中的最小元素
public int getMin() {
return stackMin.peek();
}
}
方法二:
(1)压入数据规则
假设当前数据为newNum,先将其压入stackData。然后判断stackMin是否为空。如果为空,则newNum也压入stackMin;如果不为空,则比较newNum和stackMin的栈顶元素中哪一个更小。
如果newNum更小或者两者相等,则newNum也压入stackMin;如果stackMin中栈顶元素小,则把stackMin的栈顶元素重复压入stackMin,即在栈顶元素上再压入一个栈顶元素。
(2)弹出数据规则
在stackData中弹出数据,弹出的数据即为value;弹出stackMin中的栈顶,返回value。
(3)查询当前栈中的最小值操作
由于上文的压入数据规则和弹出数据规则可知,stackMin始终记录着stackData中的最小值,所以stackMin的栈顶元素始终是当前stackData中的最小值。
import java.util.Stack;
/**
* 1、设计一个有getMin功能的栈
*
* 【题目】
*
* 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
*
* 【要求】
*
* 1. pop、push、getMin操作的时间复杂度都是O(1)
* 2. 设计的栈类型可以使用线成的栈结构
*/
// 方法二
public class MyStack2 {
//普通栈保存栈中的元素,功能和一个正常的栈没有区别
private Stack<Integer> stackData;
//保存每一步的最小值
private Stack<Integer> stackMin;
public MyStack2() {
this.stackData = new Stack<Integer>();
this.stackMin = new Stack<Integer>();
}
//压栈
public void push(int newNum) {
// 判断存放最小值的栈是否为空,不为空直接入栈
if (this.stackMin.isEmpty()) {
this.stackMin.push(newNum);
} else if (newNum < this.getMin()) { // 判断当前元素是否要入stackMin中,和stackMin的栈顶元素进行比较,若发现newNum更小则入栈,反之不入stackMin栈
this.stackMin.push(newNum);
} else {
this.stackMin.push(this.stackMin.peek());
}
// 所有的新元素都会入StackData栈
this.stackData.push(newNum);
}
//出栈
public int pop() {
// 判断栈中元素是否为空
if (this.stackData.isEmpty()) {
throw new RuntimeException("栈中元素为空!");
}
this.stackMin.pop();
return this.stackData.pop();
}
//获取stackMin栈中的栈顶元素,stackMin栈中保存的每一次入栈的最小值
private int getMin() {
if (this.stackMin.isEmpty()) {
throw new RuntimeException("栈中元素为空!");
}
// Java利用Stack类的peek()函数获取堆栈中的顶部元素
return this.stackMin.peek();
}
}
注意:方法一是更加好的方法
01_设计一个有getMin功能的栈的更多相关文章
- 算法与数据结构题目的 PHP 实现:栈和队列 设计一个有 getMin 功能的栈
刚入手了一本<程序员代码面试指南>,书中题目的代码都是 Java 实现的,琢磨着把这些代码用 PHP 敲一遍,加深印象. 题目:设计一个有 getMin 功能的栈 —— 实现一个特殊的栈, ...
- 设计一个有getMin功能的栈
[说明]: 本文是左程云老师所著的<程序员面试代码指南>第一章中“设计一个有getMin功能的栈”这一题目的C++复现. 本文只包含问题描述.C++代码的实现以及简单的思路,不包含解析说明 ...
- 《程序员代码面试指南》第一章 栈和队列 设计一个有getMin功能的栈
题目 实现一个特殊的栈,在实现栈的基本功能上,再实现返回栈中最小的元素的操作 要求 1. pop.push.getMin操作时间复杂度都是O(1) 2. 设计的栈类型可以使用现成的栈结构 java代码 ...
- 栈和队列----设计一个有getMin功能的栈
设计一个有getMin功能的栈 设计一个具有getMin功能的栈,可以返回栈中的最小的元素,可以使用现有的栈的数据结构,要求pop/push/getMin操作的时间复杂度是O(1). package ...
- 栈和队列问题:设计一个有 getMin 功能的栈
[知识点] 栈是一个先进后出(FILO-First In Last Out)的数据结构,队列是一种先进先出(FIFO-First In First Out)的数据结构. [题目] 实现一个特殊的栈,在 ...
- 设计一个有getMin功能的栈(2)
题目: 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作. 要求: 1.pop.push.getMin操作的时间复杂度都是O(1) 2.设计的栈类型可以输用现成的栈结构 解答 ...
- 设计一个有getMin功能的栈(1)
题目: 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作. 要求: 1.pop.push.getMin操作的时间复杂度都是O(1) 2.设计的栈类型可以输用现成的栈结构 解答 ...
- 常见面试算法题JS实现-设计一个有getMin功能的栈
前言: 已经确定工作了-下周一正式入职,按理说应该是可以好好浪荡一周的,但是内心总是不安,总觉得自己这个水平真的太菜了,还是趁着现在有自己的时间,赶紧多看看书,多学习学习吧orz所以把之前校招买的书, ...
- 左神算法书籍《程序员代码面试指南》——1_01设计一个有getMin功能的栈
[题目] 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作. [要求] 1.pop.push.getMin操作的时间复杂度都是O(1).2.设计的栈类型可以使用现成的栈结构. ...
- 设计一个带有getmin功能的栈,保证时间复杂度在O(1)
2017-06-22 20:56:10 需要得到最小值,最简单的思路就是遍历一遍求出最小值.但是这样的时间复杂度会是O(n),不满足O(1)的要求.于是想到在建立一个栈来保存最小值. 具体操作是建立 ...
随机推荐
- The fourth day learning summary
一.for 循环循环就是重复做某件事,for循环是python提供第二种循环机制(第一种是while循环),理论上for循环能做的事情,while循环都可以做.目的:之所以要有for循环,是因为for ...
- 华企盾DSC由于半透明软件设置了需要管理员权限打开导致半透明打不开加密文件
解决方法: 1.右键该应用程序->属性->兼容性,去掉[以管理员权限运行此程序] 2.也可以打开控制面板->系统和安全->用户账户控制设置调至最低
- libGDX游戏开发之Sprite、Texture和TextureRegion绘制旋转、反转(九)
libGDX游戏开发之Sprite.Texture和TextureRegion绘制反转(九) libGDX系列,游戏开发有unity3D巴拉巴拉的,为啥还用java开发?因为我是Java程序员emm- ...
- mysql 数据库 定时 备份到阿里云盘
仓库地址: gitee:db_backup_script: mysql 数据库 定时/实时 备份数据库到阿里云盘,备份成功后消息可通知到钉钉群.企业微信群.wxpusher (gitee.com gi ...
- 春眠不觉晓,Java数据类型知多少?基础牢不牢看完本文就有数了
文编|JavaBuild 哈喽,大家好呀!我是JavaBuild,以后可以喊我鸟哥!俺滴座右铭是不在沉默中爆发,就在沉默中灭亡,一起加油学习,珍惜现在来之不易的学习时光吧,等工作之后,你就会发现,想学 ...
- WinForm如何将子控件插入FlowLayoutPanel开始位置
需求描述 动态将控件插入到FlowLayoutPanel控件的开始位置 实现方案 将控件添加到FlowLayoutPanel的Controls集合中,默认插到末尾 使用SetChildIndex方法更 ...
- Asp .Net Core 系列:基于 Swashbuckle.AspNetCore 包 集成 Swagger
什么是 Swagger? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.它提供了一种规范的方式来定义.构建和文档化 RESTful Web ...
- 使用 Zpan 搭建低成本个人私有网盘,还不限速
摘要:本文就介绍一个不限速的低成本个人网盘--ZPan,相较于老牌的私有网盘 OwnCloud 等,Zpan 有一个独有的优势:不限速. 本文分享自华为云社区<使用 Zpan 搭建低成本个人私有 ...
- Spring中部署Activiti流程定义的三种姿势
摘要:本文对工作流Activiti框架中流程定义的部署进行了详细说明介绍. 本文分享自华为云社区<项目中工作流部署详细解析!Spring中部署Activiti流程定义的三种姿势>,作者:攻 ...
- 使用formdata在vue和django之间传递文件
在前端页面中如果有文件或者图片需要上传的场景下,通用做法是使用formdata将文件从前端传输到后台,在后台上传文件并将url保存在数据库. 当前项目是使用vue + Element UI + dja ...