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

    实现效果: 源代码: import urllib.request import json import msvcrt kd_dict = {1:'shentong',2:'youzhengguonei ...

  2. C/C++代码规范

    零.前言 笔者最近在看开源代码,看到代码格式各自参差不齐,感觉像是各家各有所长.因此打算写一篇关于C/C++代码规范文章,请各位参考,并践踏批评. 一.文件排版 1. 包含头文件 • 先系统头文件,后 ...

  3. Python&Selenium&pytest借助allure生成自动化测试报告

    一.摘要 本篇博文将介绍Python和Selenium进行自动化测试时,如何借助allure生成自动化测试报告 二.环境配置 首先python环境中安装pytest和pytest_allure_ada ...

  4. [JLOI2009]神秘的生物——轮廓线DP

    原题链接 题目大意 \(n\times n\)的带权方阵,选一个权值最大的连通块 Solution 一眼连通性DP,然后就没了 转移很好想的啦,简单讨论一下就行了 有一个坑点,就是不能一个格子都不选, ...

  5. 牛客CSP-S提高组赛前集训营3

    A 货物收集 显然是一个二分答案的题. #include<iostream> #include<cstdio> #include<cstring> #include ...

  6. C# 字符串和正则表达式(8) 持续更新

    创建字符串 如果多次修改一个字符串或创建一个很长的字符串,用String类会效率低下.这种情况,可以用 System.Text.StringBuilder ,它专门为这种情况设计的. 格式化表达式 格 ...

  7. 基于Ajax技术的前后端Json数据交互方式实现

    前言 使用浏览器访问网站是日常生活中必不可少的一件事情,当我们在浏览器地址栏中输入网址后会看到网站的内容,那么这个过程中发生了什么?下面简单介绍下浏览器访问网站过程. 第一步:浏览器向DNS服务器发起 ...

  8. Hbuilder + MUI 的简单案例

    话不多说 直接上代码 项目结构: index.html 的代码 <!DOCTYPE html><html>    <head>        <meta ch ...

  9. 牛客练习赛3 贝伦卡斯泰露——队列&&爆搜

    题目 链接 题意:给出一个长度为 $n$ 的数列 $A_i$,问是否能将这个数列分解为两个长度为n/2的子序列,满足: 两个子序列不互相重叠(是值不能有共同元素,但位置可以交错). 两个子序列中的数要 ...

  10. MacOs High Sierra 升级失败解决办法

    进入recovery的方法: Command-R 重新安装您在 Mac 上安装过的最新 macOS,但不会升级到更高的版本. Option-Command-R升级到与您的 Mac 兼容的最新 macO ...