【LeetCode】剑指 Offer 30. 包含min函数的栈
题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 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函数的栈的更多相关文章
- 剑指 Offer 30. 包含min函数的栈 + 双栈实现求解栈中的最小值
剑指 Offer 30. 包含min函数的栈 Offer_30 题目描述: 题解分析: 题目其实考察的是栈的知识,本题的目的是使用两个栈来求解最小值. 第二个栈主要用来维护第一个栈中的最小值,所以它里 ...
- 剑指 Offer 30. 包含min函数的栈
剑指 Offer 30. 包含min函数的栈 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min.push 及 pop 的时间复杂度都是 O(1). 示例 ...
- 力扣 - 剑指 Offer 30. 包含min函数的栈
题目 剑指 Offer 30. 包含min函数的栈 思路1 使用一个辅助栈min_stack,用来维护栈的最小的元素 每次添加元素入栈时候,data_stack和min_stack都要同时维护 dat ...
- 【Java】 剑指offer(30) 包含min函数的栈
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min ...
- 每日一题 - 剑指 Offer 30. 包含min函数的栈
题目信息 时间: 2019-06-24 题目链接:Leetcode tag:栈 难易程度:简单 题目描述: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 m ...
- 剑指offer——30包含min函数的栈
题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 题解: 借助辅助栈,新的数据<=f辅助栈顶时,就压入辅助栈,这样,就能保证辅 ...
- [剑指offer] 5. 用两个栈实现队列+[剑指offer]30. 包含min函数的栈(等同于leetcode155) +[剑指offer]31.栈的压入、弹出序列 (队列 栈)
c++里面stack,queue的pop都是没有返回值的, vector的pop_back()也没有返回值. 思路: 队列是先进先出 , 在stack2里逆序放置stack1的元素,然后stack2. ...
- 《剑指offer》 包含min函数的栈
本题来自<剑指offer> 包含min函数的栈 题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 思路: 举例子让抽象问题具体 ...
- 【剑指Offer】包含min函数的栈 解题报告
[剑指Offer]包含min函数的栈 解题报告 标签(空格分隔): 牛客网 题目地址:https://www.nowcoder.com/questionTerminal/beb5aa231adc45b ...
- Go语言实现:【剑指offer】包含min函数的栈
该题目来源于牛客网<剑指offer>专题. 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数. 时间复杂度应为O(1). Go语言实现: var myList = ...
随机推荐
- ELK 性能优化实践
文章转载自:https://mp.weixin.qq.com/s?__biz=MzI5MTU1MzM3MQ==&mid=2247489814&idx=1&sn=6916f8b7 ...
- vue 自定义千位符过滤器
在main.js页面全局引入 Vue.filter('formatNum', function(value) { if(!value) return '' let num = value.toStri ...
- [CG从零开始] 3. 安装 pyassimp 库加载模型文件
assimp 是一个开源的模型加载库,支持非常多的格式,还有许多语言的 binding,这里我们选用 assimp 的 python 的 binding 来加载模型文件.不过社区主要是在维护 assi ...
- Linux下多线程创建
1.pthread_create Linux中线程创建用pthread_create函数 #include <pthread.h> int pthread_create( pthread_ ...
- Codeforces Round #709 Div2
就ac了一题.QAQ掉分了我好难过. A题要画图推出来公式. B不会,现在没看到好懂得题解. C题,思路错了,给一些数,每天只能选其中一些,每个数不能被选超过k次,应该先将每天只能选一个得这个数先选上 ...
- .NET 7 RC 2 发布,倒计时一个月发布正式版
微软2022-10-22 发布了 .NET 7 RC 2,下一站是.NET 7正式发布,就在下个月Net Conf 2022(11月8日)期间正式发布. 经过长达一年时间的开发,.NET 7 规划的所 ...
- .NET 采用 SkiaSharp 生成二维码和图形验证码及图片进行指定区域截取方法实现
在最新版的 .NET 平台中,微软在逐步放弃 System.Drawing.Imaging ,给出的理由如下: System.Drawing命名空间对某些操作系统和应用程序类型有一些限制. 在Wind ...
- Dubbo-聊聊注册中心的设计
前言 Dubbo源码阅读分享系列文章,欢迎大家关注点赞 SPI实现部分 Dubbo-SPI机制 Dubbo-Adaptive实现原理 Dubbo-Activate实现原理 Dubbo SPI-Wrap ...
- 22.通用视图GenericAPIView、属性和方法
generics.ListCreateAPIView #源码 class ListCreateAPIView(mixins.ListModelMixin, mixins.CreateModelMixi ...
- 19.drf response及源码分析
源代码位于:response.py REST framework 提供一个 Response 类来支持 HTTP内容协商,该类允许返回可以呈现为多种类型的内容,具体取决于客户端的请求. 这个 ...