包含min函数的栈、队列
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈/队列的最小元素的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函数的栈、队列的更多相关文章
- 剑指Offer面试题:19.包含Min函数的栈
一.题目:包含Min函数的栈 题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数.在该栈中,调用min.push及pop的时间复杂度都是O(1). 这里我们要实现的就是min ...
- 【编程题目】设计包含 min 函数的栈
2.设计包含 min 函数的栈(栈)定义栈的数据结构,要求添加一个 min 函数,能够得到栈的最小元素.要求函数 min.push 以及 pop 的时间复杂度都是 O(1). 我的思路: 用一个额外的 ...
- 【面试题021】包含min函数的栈
[面试题021]包含min函数的栈 MinStack.cpp: 1234567891011121314151617181920212223242526272829303132333435363738 ...
- 面试经典-设计包含min函数的栈
问题:设计包含min函数的栈(栈) 定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素. 要求函数min.push以及pop的时间复杂度都是O(1). 解答:push 和pop的时间复杂度 ...
- 包含min函数的栈 ,二叉树的镜像
包含min函数的栈 问题 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 代码 # -*- coding:utf-8 -*- class Sol ...
- 算法: 包含min函数的栈
* @Description 包含min函数的栈* @问题:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)).* @思路: 1:Stack 类中的p ...
- 《剑指offer》 包含min函数的栈
本题来自<剑指offer> 包含min函数的栈 题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 思路: 举例子让抽象问题具体 ...
- 41. 包含min函数的栈
包含min函数的栈 描述 设计一个支持push,pop,top等操作并且可以在O(1)时间内检索出最小元素的堆栈. push(x)–将元素x插入栈中 pop()–移除栈顶元素 top()–得到栈顶元素 ...
- 《剑指offer》第三十题(包含min函数的栈)
// 面试题30:包含min函数的栈 // 题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min // 函数.在该栈中,调用min.push及pop的时间复杂度都是O(1). #i ...
随机推荐
- VSCode 快捷键定义
默认的 Toggle explore side bar 快捷键为 Ctrl + B, 但是这和 Vim 的快捷键冲突,解决方法: File > Preferences > Keyb ...
- java线程基础巩固---采用多线程方式模拟银行排队叫号以及Runnable接口存在的必要性
采用多线程模拟银行排队叫号: 关于银行拿排队号去叫号的过程我想不必过多解释了,就是有几个业务窗口,并行的处理业务,每处里完一个人,则会叫下一个排队的号去处理业务,一个人是不会被多个窗口工作人员叫号的, ...
- 双端队列 C. Vasya and String
High school student Vasya got a string of length n as a birthday present. This string consists of le ...
- Python数据库连接池 -组件 DBUtils
DBUtils是Python的一个用于实现数据库连接池的模块 此连接池有两种连接模式: DBUtils提供两种外部接口: PersistentDB :提供线程专用的数据库连接,并自动管理连接. Poo ...
- visual studio 和visual studio code 的区别是什么?
区别有三: 区别一:含义不一样. Visual Studio(简称VS)是美国微软公司的开发工具包系列产品,是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具.代码 ...
- C#主菜单动态添加子菜单并设置触发事件
我所使用的是devxepress中的主菜单栏时barsubitem控件,想的是在其能够动态添加子菜单栏并能点击触发事件: /// <summary> /// 创建主按钮的子按钮 /// & ...
- sql防止注入的技巧
from Stack Overflow Here is a similar solution which I think is more efficient in building up the li ...
- MyBatis中#{}和${}的不同和${}的妙用(转)
突然意识到sql语句的独特语义要和代码分离,我们就不能够在代码中写sql语句!!比如我要用${}在MyBatis的sql中拼接排序类型的时候,我就不能够在Java代码中直接写参数字符串为Ord ...
- Vivado与Modelsim联合仿真
[转载]: 1:https://blog.csdn.net/weixin_37603007/article/details/82823965 2:https://blog.csdn.net/Piece ...
- 【线性代数】1-1:线性组合(Linear Combinations)
title: [线性代数]1-1:线性组合(Linear Combinations) toc: true categories: Mathematic Linear Algebra date: 201 ...