题目描述

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 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. Service概述

    为何需要 Service Kubernetes 中 Pod 是随时可以消亡的(节点故障.容器内应用程序错误等原因).如果使用 Deployment 运行您的应用程序,Deployment 将会在 Po ...

  2. .Net 7 C#11 原始字符串

    .Net7 的到来的同时,也带来了 C# 11,而令我最期待的就是 C# 11 的 原始字符串了,当我知道这个的时候,简直比过年还要开心. 非原始字符串 首先我们看看现在写字符串的方式 var str ...

  3. 玩转Google开源C++单元测试框架Google Test系列(gtest)之八 - 打造自己的单元测试框架

    转载来源:https://www.cnblogs.com/coderzh/archive/2009/04/12/1434155.html 一.前言 上一篇我们分析了gtest的一些内部实现,总的来说整 ...

  4. AgileBoot - 手把手一步一步带你Run起全栈项目(SpringBoot+Vue3)

    AgileBoot是笔者在业余时间基于ruoyi改造优化的前后端全栈项目. 关于AgileBoot的详细介绍:https://www.cnblogs.com/valarchie/p/16777336. ...

  5. 撸了一个简易的配置中心,顺带整合到了SpringCloud

    大家好,我是三友~~ 最近突然心血来潮(就是闲的)就想着撸一个简单的配置中心,顺便也照葫芦画瓢给整合到SpringCloud. 本文大纲 配置中心的概述 随着历史的车轮不断的前进,技术不断的进步,单体 ...

  6. Java学习之路:运算符

    2022-10-10 10:34:08 1 运算符 算术运算符:+, -, *, /, %, ++, -- 赋值运算符:= 关系运算符:>, <, >=, <=, ==, != ...

  7. Codeforces Round #830 (Div. 2) A-D

    比赛链接 A 题解 知识点:贪心,数论. 先求出序列最大公约数 \(d\) ,如果为 \(1\) 直接输出 \(0\) . 否则,尝试用最后一个数操作, \(gcd(d,n) = 1\) 则可以,花费 ...

  8. 快读《ASP.NET Core技术内幕与项目实战》EFCore2.5:集合查询原理揭秘(IQueryable和IEnumerable)

    本节内容,涉及4.6(P116-P130).主要NuGet包:如前述章节 一.LINQ和EFCore的集合查询扩展方法的区别 1.LINQ和EFCore中的集合查询扩展方法,虽然命名和使用完全一样,都 ...

  9. certutil做哈希校验并下载网络文件

    微软Win系统自带,不需要安装的工具,但它是CMD命令行工具,关于命令行工具的说明和使用请参考我以前的文章 Windows系统的命令行(CLI)介绍及入门使用说明 . 这个微软自带的命令行工具叫做 c ...

  10. PageRank原理分析

    pagerank是将众多网页看成一个有向图,每个页面就是有向图中的节点.计算每个节点的出度和入度.如果一个网站被大量其他的网页引用,那么他就会有更高的pr分数. 原理 对于所有与节点i相连的节点,用他 ...