题目:定义栈的数据结构,请在该类型中实现一个能够得到栈/队列的最小元素的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. IPV4和IPV6的划分

    IP(Internet Protocol,网络互联协议)地址就是连接互联网的主机被分配或指派的一段数字标识,是传输报文组装时最重要的组成部分,用来在互联网中数据传输时标识源和目标主机. IPv4 IP ...

  2. JAVA8初探-让方法参数具备行为能力并引入Lambda表达式

    关于JAVA8学习的意义先来贴一下某网站上的对它的简单介绍:“Java 8可谓Java语言历史上变化最大的一个版本,其承诺要调整Java编程向着函数式风格迈进,这有助于编写出更为简洁.表达力更强,并且 ...

  3. Python3学习笔记36-PEP8代码规范

    在使用PyCharm时,最右边会有波浪线警告提示代码不符合PEP8代码规范.记录一下犯的错和解决方式 PEP8是风格错误,而不是编码错误.只是为了让代码更具有阅读性. 1)block comment ...

  4. P5025 [SNOI2017]炸弹 题解

    蒟蒻的第一篇黑题题解(学了这么长时间了才第一道也是没谁了.) 题目链接: Solution: 朴素: 根据题目描述,我们可以处理每一个x节点左右爆炸半径范围内的点,然后模拟一次爆炸 (for),遍历每 ...

  5. python_tkinter组件摆放方式

    1.最小界面组成 # 导入tkinter模块 import tkinter # 创建主窗口对象 root = tkinter.Tk() # 设置窗口大小(最小值:像素) root.minsize(30 ...

  6. idea如何打开右侧工具栏

  7. vue初级尝试

    为了跟上前端后台化的潮流,本少不得不开始关注vue,下列上机代码是针对App.vue进行的更改 数据渲染----一般键值对,数组,对象和对象数组 <template> <div id ...

  8. struts2之登陆拦截

    针对登录拦截功能,我们需要设置拦截哪些方法和不拦截哪些方法 action action类中,处理登录时,将用户.密码绑定到session ActionContext ac = ActionContex ...

  9. Bootstrap-轮播图-No.7

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  10. (三)根据向导创建MFC工程,事件的添加和删除

    一,文档视图结构 文档:它是一个类,这个类专门用来存储数据 视图:它是一个类,这个类专门用来显示和修改数据 框架类:一个容器,这个容器装了视图 健完工程之后,类视图: 运行一下: 几个比较重要的函数 ...