题目:定义栈的数据结构,请在该类型中实现一个能够得到栈/队列的最小元素的min函数。在该栈/队列中,调用min、入栈(入队列)及出栈(出队列)函数的时间复杂度都是O(1)。

1. 包含min函数的栈

  看到这个问题,第一反应是创建一个成员变量保存栈中当前的最小元素。每次压入一个新元素进栈时,如果该元素比当前最小的元素还要小,则更新最小元素。采用这种思路,元素入栈的时候没有问题,但出栈时如果最小的元素被弹出栈了,就无法得到下一个最小的元素。如图,元素入栈出栈过程如下,当元素3出栈时,无法确定栈中当前最小元素4。

元素入栈出栈过程分析

  分析到这里,我们发现仅仅添加一个成员变量存放最小元素时不够的,也就是当最小元素被弹出栈的时候,我们希望能够得到次小元素。因此,在压入这个最小元素之前,需要把次小元素保存起来,于是采用一个“辅助栈”保存历史最小元素。还是以上面的入栈出栈为例,多了一个辅助栈,当元素3出栈时,依然可以的到栈的当前最小元素。

元素入栈出栈过程分析

算法的代码实现如下:

 import java.util.LinkedList;
import java.util.Stack; public class d30_MinInStack {
public static void main(String[] args) {
// 测试包含min函数的栈
StackWithMin<Integer> stack = new StackWithMin<>();
stack.push(3);
stack.push(4);
stack.push(2);
stack.pop(); // 当前最小元素出栈,则minStack最小元素也要出栈
stack.push(0);
stack.push(-1);
System.out.println(stack.dataStack); // [3, 4, 0, -1]
System.out.println(stack.minStack); // [3, 0, -1]
System.out.println(stack.min()); // -1
} /*
* 包含min函数的栈
*/
static class StackWithMin<T extends Comparable<T>> {
private Stack<T> dataStack; // 记录实际元素的栈
private Stack<T> minStack; // 记录最小元素的栈 public StackWithMin() {
this.dataStack = new Stack<>();
this.minStack = new Stack<>();
} /*
* 元素入栈
*/
public void push(T data) {
if (data == null) {
throw new RuntimeException("cannot push null");
}
if (dataStack.isEmpty()) {
dataStack.push(data);
minStack.push(data);
} else {
dataStack.push(data);
// 记录最小栈的当前最小元素
T curMin = minStack.peek();
// 新入栈函数小于curMin
if (data.compareTo(curMin) < 0) {
minStack.push(dataStack.peek());
}
}
} /*
* 元素出栈
*/
public T pop() {
if (dataStack.isEmpty()) {
throw new RuntimeException("dataStack is empty!");
}
// 如果出栈元素为dataStack栈的当前最小元素,minStack的栈顶元素出栈
if (dataStack.peek() == minStack.peek()) {
minStack.pop();
}
return dataStack.pop();
} /*
* 取栈中最小元素
*/
public T min() {
if (minStack.isEmpty()) {
throw new RuntimeException("minStack is empty!");
}
return minStack.peek();
}
}
}

2. 包含min函数的队列

  有了上面对栈的分析作为基础,实现包含min函数的队列就比较容易了。实现思路还是创建“辅助队列”,但与“辅助栈”不同的是,“辅助队列”并不是保存队列中历史最小元素。如果不是最小元素入队列,则“辅助队列”以递减的方式保存元素;如果是最小元素入队列,则“辅助队列”将其他元素出队,只保存该最小元素。具体的过程如下图所示:

元素入队出队过程分析

算法实现代码如下:

 import java.util.LinkedList;
import java.util.Stack; public class d30_MinInStack { public static void main(String[] args) {
// 测试包含min函数的队列
QueueWithMin<Integer> queue = new QueueWithMin<>();
queue.enqueue(3);
queue.enqueue(4);
queue.enqueue(7);
System.out.println(queue.min());
queue.enqueue(5);
System.out.println();
System.out.println(queue.min());
} /*
* 包含min函数的队列
*/
public static class QueueWithMin<T extends Comparable<T>> {
private LinkedList<T> dataQueue;
private LinkedList<T> minQueue; public QueueWithMin() {
dataQueue = new LinkedList<>();
minQueue = new LinkedList<>();
} // 元素入队
public void enqueue(T data) {
if (data == null) {
throw new RuntimeException("cannot enqueue null");
}
dataQueue.offer(data);
// 保证minQueue队列的元素递减
// 若data < 队头元素,则minQueue队头元素出队
while (!minQueue.isEmpty() && (data.compareTo(minQueue.peek()) < 0)) {
minQueue.poll();
}
// 若data < 队尾元素,则minQueue队尾元素出队
while(!minQueue.isEmpty() && (data.compareTo(minQueue.peekLast()) < 0)) {
minQueue.poll();
}
minQueue.offer(data);
} // 元素出队
public T dequeue() {
if (dataQueue.isEmpty()) {
throw new RuntimeException("dataQueue is empty!");
}
// dataQueue出队元素与minQueue队头元素相等,则minQueue队头元素出队
if (dataQueue.peek() == minQueue.peek()) {
minQueue.poll();
}
return dataQueue.poll();
} // 取队列最小元素
public T min() {
if (minQueue.isEmpty()) {
throw new RuntimeException("minQueue is empty!");
}
return minQueue.peek();
}
}
}

包含min函数的栈、队列的更多相关文章

  1. 剑指Offer面试题:19.包含Min函数的栈

    一.题目:包含Min函数的栈 题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数.在该栈中,调用min.push及pop的时间复杂度都是O(1). 这里我们要实现的就是min ...

  2. 【编程题目】设计包含 min 函数的栈

    2.设计包含 min 函数的栈(栈)定义栈的数据结构,要求添加一个 min 函数,能够得到栈的最小元素.要求函数 min.push 以及 pop 的时间复杂度都是 O(1). 我的思路: 用一个额外的 ...

  3. 【面试题021】包含min函数的栈

    [面试题021]包含min函数的栈  MinStack.cpp: 1234567891011121314151617181920212223242526272829303132333435363738 ...

  4. 面试经典-设计包含min函数的栈

    问题:设计包含min函数的栈(栈) 定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素. 要求函数min.push以及pop的时间复杂度都是O(1). 解答:push 和pop的时间复杂度 ...

  5. 包含min函数的栈 ,二叉树的镜像

    包含min函数的栈 问题 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 代码 # -*- coding:utf-8 -*- class Sol ...

  6. 算法: 包含min函数的栈

    * @Description 包含min函数的栈* @问题:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)).* @思路: 1:Stack 类中的p ...

  7. 《剑指offer》 包含min函数的栈

    本题来自<剑指offer> 包含min函数的栈 题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 思路: 举例子让抽象问题具体 ...

  8. 41. 包含min函数的栈

    包含min函数的栈 描述 设计一个支持push,pop,top等操作并且可以在O(1)时间内检索出最小元素的堆栈. push(x)–将元素x插入栈中 pop()–移除栈顶元素 top()–得到栈顶元素 ...

  9. 《剑指offer》第三十题(包含min函数的栈)

    // 面试题30:包含min函数的栈 // 题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min // 函数.在该栈中,调用min.push及pop的时间复杂度都是O(1). #i ...

随机推荐

  1. 将excel表格导入到DataGridView

    using System.Data.OleDb; 添加一个button控件,一个textBox控件,用于显示选择路径  private void loadxls() { String fileName ...

  2. 9种Java单例模式详解(推荐)

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象.  懒汉式(线程不安全) 其主要表现在单例类在外 ...

  3. glRenderbufferStorageMultisample

    https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glRenderbufferStorage.xhtml https://www. ...

  4. oracle之约束-主键、非空、唯一、check、外键、默认

    --首先添加主键约束alter table studentadd constraint PK_student_sno primary key(sno) --删除约束alter table studen ...

  5. BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 (LCT维护连通性)

    直接把x设为根,然后查询y所在联通块的根是不是x就行了. CODE #include <cstdio> #include <cstring> #include <algo ...

  6. crypot.js 生成hash256, 在IE下的卡顿问题。

    项目需求: 上传大文件,调用crypto.js生成hash256码. 直接上传大文件,IE会直接崩溃. 于是利用file.slice分片检测.但是浏览器会出现卡顿问题.开始以为是内存泄漏.但看服务器进 ...

  7. java+上传整个文件夹的所有文件

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 首先我们需要了解的是上传文件三要素: 1.表单提交方式:post (get方式提交有大小 ...

  8. 路由器配置——路由重分布1(rip)

    一.实验目的:使用路由重分布达到全网互通 二.拓扑图: 三.具体实验步骤配置 先给各个主机配置ip地址和网关以PC1为例: (1)R1路由器配置 Router>enable  --进入特权模式R ...

  9. spoj5973

    SP5973 SELTEAM - Selecting Teams #include <bits/stdc++.h> using namespace std; typedef long lo ...

  10. Python3 Address already in use 解决方法

    1.查看使用端口号netstat -ntlp 2.根据端口号找到pid 3.杀死程序 kill -9 pid 4.重新启动程序 简单粗暴 我使用python3时编写Socket,linux系统下使用c ...