01_设计一个有getMin功能的栈

【题目】

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

【要求】

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

方法一:

【思路】我们使用两个栈,一个栈用来保存当前栈中的元素,其功能和一个正常的栈没有区别,这个栈记为 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功能的栈的更多相关文章

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

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

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

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

  3. 《程序员代码面试指南》第一章 栈和队列 设计一个有getMin功能的栈

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

  4. 栈和队列----设计一个有getMin功能的栈

    设计一个有getMin功能的栈 设计一个具有getMin功能的栈,可以返回栈中的最小的元素,可以使用现有的栈的数据结构,要求pop/push/getMin操作的时间复杂度是O(1). package ...

  5. 栈和队列问题:设计一个有 getMin 功能的栈

    [知识点] 栈是一个先进后出(FILO-First In Last Out)的数据结构,队列是一种先进先出(FIFO-First In First Out)的数据结构. [题目] 实现一个特殊的栈,在 ...

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

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

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

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

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

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

  9. 左神算法书籍《程序员代码面试指南》——1_01设计一个有getMin功能的栈

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

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

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

随机推荐

  1. [ABC261A] Intersection

    Problem Statement We have a number line. Takahashi painted some parts of this line, as follows: Firs ...

  2. 10个必备的 async/await 工具函数

    | 当谈到异步编程时,async/await是JavaScript中常用的功能之一.下面是10个常用的await和async函数示例,以及对它们的代码用途的解析: 1.异步获取数据 async fun ...

  3. 关于腾讯地图geolocation.getLocation 经常定位失败,定位时间过长的解决方法

    今天遇到个项目,腾讯地图定位出现问题,导致地图无法呈现出最近的目标 这是正常的效果,之前一直出现贵州等地点的信息,查看控制台的网络后,发现腾讯的定位失败,要么就是定位时间过长,要20S左右,但是换ED ...

  4. 用Python来查询聊天记录

    用Python来查询聊天记录 代码 import re def Start(First_Date, Second_Date, First_Name, Second_Name): First = re. ...

  5. Aware依赖注入管理

    1.Aware介绍 在Spring当中有一些内置的对象是未开放给我们使用的,例如Spring的上下文ApplicationContext.环境属性Environment,BeanFactory等等其他 ...

  6. MyBatis 的缓存处理

    作为常见的 ORM 框架,在使用 MyBatis 的过程中可以针对相关的查询进行缓存处理以提高查询的性能.本文将简要介绍一下 MyBatis 中默认的一级缓存和二级缓存,以及自定义缓存的处理 MyBa ...

  7. 七天.NET 8操作SQLite入门到实战 - 第七天BootstrapBlazor UI组件库引入(1)

    前言 由于第七天Blazor前端页面编写和接口对接的内容比较的多,所以这一章节将会分为三篇文章来进行讲解,大家可以认为分为早.中.晚来进行阶段性学习,从而提高学习效率. 七天.NET 8 操作 SQL ...

  8. table中td超出内容隐藏,鼠标悬停全部显示(完整版,含js代码)

    一.CSS语法: text-overflow:clip | ellipsis 默认值:clip 适用于:所有元素 clip: 当对象内文本溢出时不显示省略标记(...),而是将溢出的部分裁切掉. el ...

  9. OSG嵌入QT的简明总结2

    正文 我之前在这篇博文<OSG嵌入QT的简明总结>中论述了OSG在QT中显示的可视化问题.其中提到官方提供的osgQt项目(地址:https://github.com/opensceneg ...

  10. 【一行代码秒上云】Serverless六步构建全栈网站

    摘要:Serverless怎么玩?听一千道一万不如亲手来实践,跟着我们以华为云Serverless实践FunctionGraph来免费体验一下六步构建全栈网站吧 前言: Serverless怎么玩?听 ...