题目描述

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

思路

最初看到O(1)复杂度的时候,就想直接用一个min变量保存当前最小值,后来想到弹栈弹出的有可能是最小值,那么只能用辅助栈。

我的代码如下

class MinStack {
public Stack<Integer> minVal;//辅助栈
public Stack<Integer> s;//主栈
/** initialize your data structure here. */
public MinStack() {
minVal=new Stack<Integer>();
s=new Stack<Integer>();
} public void push(int x) {
s.push(x);
if(s.size()==1)//第一个元素入栈的时候,直接进入minVal
{
minVal.push(x);
}
else{//将当前元素与min值比较,如果小于等于min值,就入minVal栈中
int p=minVal.peek();
if(x<=p){//一定要加等号:如果有两个最小值,pop一个,还剩一个
minVal.push(x);
}
}
} public void pop() {
if(s.size()==0) ;
int k=s.pop();
int p=minVal.peek();
if(k==p){//若主栈弹出的元素是最小值就弹minVal栈
minVal.pop();
}
} public int top() {
if(s.size()==0) return -1;
return s.peek();
} public int min() {
if(minVal.size()==0) return -1;
return minVal.peek();
}
} /**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(x);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.min();
*/

改进思路

改进解法:只需要一个栈

思路

依然设置一个min变量记录当前最小值,但是当元素b(b<min)入栈时,需要做两步:

1.min入栈

2.b入栈

那么在弹栈时,若将要弹出的是当前min,就把min设置为栈顶下面的元素,然后别忘了再pop一下。(可以直接写min=s.pop(),一句话两个操作)

图解(源自LeetCode用户@数据结构和算法):





代码

class MinStack {//push方法可能会加入很多min
int min = Integer.MAX_VALUE;
Stack<Integer> stack = new Stack<>(); public void push(int x) {
//如果加入的值小于最小值,要更新最小值
if (x <= min) {
stack.push(min);
min = x;
}
stack.push(x);
} public void pop() {
//如果把最小值出栈了,就更新最小值
if (stack.pop() == min)
min = stack.pop();
} public int top() {
return stack.peek();
} public int min() {
return min;
}
}

更优改进解法:压入当前值和min的差值

思路

由于上面改进思路存在这样的不足,即如果输入的是一个递减序列,那么每次都需要将min入栈,占用空间较大;为了改进这个问题,可以不压入当前值,而是压入当前值与min的差值,pop时,若pop的是负数,说明最小值已经出栈了,重新更新最小值。

弹栈的时候分两种情况:

1.pop出来的是个负数,说明此数应该是当前最小值,直接返回min即可

2.pop出来的是个正数a,说明此数比当前min大a,返回min+a

代码

public class MinStack {
long min;
Stack<Long> stack = new Stack<>(); public void push(int x) {
if (stack.isEmpty()) {
stack.push(0L);//最初设最小值为x,所以最小值与x的差值直接是0
min = x;
} else {
//这里入栈的是入栈的值和最小值的差值,有可能为负,也有可能为正。
stack.push(x - min);
if (x < min)
min = x;
}
} public void pop() {
if (stack.isEmpty())
return;
long pop = stack.pop();
//因为入栈的是差值,当出栈的为负数的时候,说明栈中最小值已经出栈了,
//这里要重新更新最小值
if (pop < 0)
min -= pop;
} public int top() {
long top = stack.peek();
if (top > 0) {
//栈顶元素如果是正的,说明栈顶元素压栈的时候是比栈中最小值大的,根据
//top=x - min,可以计算x=top+min
return (int) (top + min);
} else {
//当栈顶元素是负数的时候,说明栈顶元素压栈的时候是比栈中最小值小的,
//而压栈完之后他会更新最小值min,所以如果在使用上面公式肯定是不行
//的。如果栈顶元素压栈的时候比最小值小,他会更新最小值,这个最小值
//就是我们要压栈的值,所以这里直接返回min就行了。
return (int) (min);
}
} public int min() {
return (int) min;
}
}

【LeetCode】剑指 Offer 30. 包含min函数的栈的更多相关文章

  1. 剑指 Offer 30. 包含min函数的栈 + 双栈实现求解栈中的最小值

    剑指 Offer 30. 包含min函数的栈 Offer_30 题目描述: 题解分析: 题目其实考察的是栈的知识,本题的目的是使用两个栈来求解最小值. 第二个栈主要用来维护第一个栈中的最小值,所以它里 ...

  2. 剑指 Offer 30. 包含min函数的栈

    剑指 Offer 30. 包含min函数的栈 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min.push 及 pop 的时间复杂度都是 O(1). 示例 ...

  3. 力扣 - 剑指 Offer 30. 包含min函数的栈

    题目 剑指 Offer 30. 包含min函数的栈 思路1 使用一个辅助栈min_stack,用来维护栈的最小的元素 每次添加元素入栈时候,data_stack和min_stack都要同时维护 dat ...

  4. 【Java】 剑指offer(30) 包含min函数的栈

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min ...

  5. 每日一题 - 剑指 Offer 30. 包含min函数的栈

    题目信息 时间: 2019-06-24 题目链接:Leetcode tag:栈 难易程度:简单 题目描述: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 m ...

  6. 剑指offer——30包含min函数的栈

    题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)).   题解: 借助辅助栈,新的数据<=f辅助栈顶时,就压入辅助栈,这样,就能保证辅 ...

  7. [剑指offer] 5. 用两个栈实现队列+[剑指offer]30. 包含min函数的栈(等同于leetcode155) +[剑指offer]31.栈的压入、弹出序列 (队列 栈)

    c++里面stack,queue的pop都是没有返回值的, vector的pop_back()也没有返回值. 思路: 队列是先进先出 , 在stack2里逆序放置stack1的元素,然后stack2. ...

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

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

  9. 【剑指Offer】包含min函数的栈 解题报告

    [剑指Offer]包含min函数的栈 解题报告 标签(空格分隔): 牛客网 题目地址:https://www.nowcoder.com/questionTerminal/beb5aa231adc45b ...

  10. Go语言实现:【剑指offer】包含min函数的栈

    该题目来源于牛客网<剑指offer>专题. 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数. 时间复杂度应为O(1). Go语言实现: var myList = ...

随机推荐

  1. Elasticsearch中的一些重要概念:cluster, node, index, document, shards及replica

    首先,我们来看下一下如下的这个图: Cluster Cluster也就是集群的意思.Elasticsearch集群由一个或多个节点组成,可通过其集群名称进行标识.通常这个Cluster 的名字是可以在 ...

  2. reflect反射

    考虑有这么一个场景:需要根据用户输入url的不同,调用不同的函数,实现不同的操作,也就是一个WEB框架的url路由功能.路由功能是web框架里的核心功能之一,例如Django的urls. 首先,有一个 ...

  3. OSF--网络类型

    ABR:区域边界路由器ASBR:自治区域系统边界路由器区域部署原则:    存在vlink本地网络一定是有问题的.他只是作为一种过度技术,在vlink里无法实现认证! 配置:   [r2-ospf-a ...

  4. ExecutorService、Callable、Future实现有返回结果的多线程原理解析

    原创/朱季谦 在并发多线程场景下,存在需要获取各线程的异步执行结果,这时,就可以通过ExecutorService线程池结合Callable.Future来实现. 我们先来写一个简单的例子-- pub ...

  5. SQL通用语法和SQL分类

    SQL通用语法 1.SQL 语句可以单行或多行书写,以分号结尾 2.可使用空格和缩进来增强语句的可读性 3.MySQL 数据库的SQL语句不区分大小写,关键字建议使用大写 4.3种注释 单行注释: - ...

  6. 实验02_Proteus仿真数码管显示代码

    一.原理总结 利用两个寄存器R4和R5来存储两个数码管的显示效果,R4是前一个数码管显示所需,而R5是后一个数码管显示所需,利用左移操作RLC来使之每一位被依次输入到C中,然后将C输入到LED中(当L ...

  7. sql limit函数

    select * from <表名> order by <列名> desc limit <第几位数>; select * from villa_info order ...

  8. vue实现功能 单选 取消单选 全选 取消全选

    vue实现功能 单选 取消单选 全选 取消全选 代码部分 <template> <div class=""> <h1>全选框</h1> ...

  9. python字典推导&&列表推导&&输出随机数

    字典推导: x = ['A', 'B', 'C', 'D'] y = ['Alice', 'Bob', 'Cecil', 'David'] print({i:j for i,j in zip(x,y) ...

  10. javascript编程单线程之异步模式Asynchronous

    异步模式Asynchronous 不会等待这个任务结束才开始执行下一个任务,开启之后立即执行下一个任务,后续逻辑一般会通过回调函数的方式定义,异步模式对js 非常重要,没有异步任务单线程的 js 语言 ...