java数据结构与算法刷题-----LeetCode155. 最小栈

news2025/1/20 4:41:46
java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

在这里插入图片描述

1. 法一:使用辅助最小栈

解题思路:时间复杂度O(1),空间复杂度O(n)
  1. 我们出栈和入栈时,要同步维护一个最小值栈
  2. 最小值栈主要保存当前最小值
  3. 这样,我们就可以实时获取当前栈中最小值
  4. 图解如下:
  1. 入栈-2,则栈顶元素为-2,当前最小值也是-2
    在这里插入图片描述
  2. 入栈0,此时栈顶为0,但是最小值还是-2,所以最小栈依然入栈-2
    在这里插入图片描述
  3. 入栈-3,当前最小值为-2,但是-3比-2小,所以最小栈入栈-3
    在这里插入图片描述
  4. 此时执行getMin()操作获取当前最小值,那么直接获取最小栈的栈顶-3.
  5. 此时执行出栈操作,那么栈顶元素为-3. 同样的,最小栈也需要出栈
    在这里插入图片描述
  6. 此时执行top操作,也就是获取栈顶元素,那么直接获取栈顶的0即可
  7. 再次执行getMin()获取最小值,那么直接获取最小栈的栈顶-2即可。
代码

在这里插入图片描述

class MinStack {
    //用链表模拟栈,作为栈存储的容器
    class ListNode {
        int val;//当前结点的值
        int min;//当前最小值。用一个变量模拟最小值栈
        ListNode next;//下一个结点

        public ListNode() {

        }

        public ListNode(int val, int min, ListNode next) {
            this.val = val;
            this.min = min;//min就是最小值栈
            this.next = next;
        }
    }

    ListNode head;//头结点

    public MinStack() {
        head = new ListNode();//头结点初始化
    }
    //入栈操作
    public void push(int val) {
        ListNode next = head.next, cur;//获取栈顶元素next,cur是当前要插入结点
        if (next != null && next.min < val) {//如果栈不为空
            //但是当前栈中最小值,比val更小,那么将当前结点入栈,但是最小值依然保存next.min
            cur = new ListNode(val, next.min, next);
        }
        else {//如果栈为空,直接入栈当前结点
            //或者栈不为空,但是当前结点的值更小的话,那么新的最小值为当前的val值
            cur = new ListNode(val, val, next);
        }
        head.next = cur;//头插法,实现先入后出
    }
    //出栈
    public void pop() {
        ListNode del = head.next;//取出栈顶元素
        head.next = del.next;//头结点指向新的栈顶元素
    }
    //获取栈顶元素的值
    public int top() {
        return head.next.val;
    }
    //获取最小值,就在栈顶元素的min变量中保存
    public int getMin() {
        return head.next.min;
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

1. 法二:使用差值

解题思路:时间复杂度O(1), 空间复杂度O(1)
  1. 用变量min保存当前栈中最小值,而入栈时,保存当前值与最小值的差值
  1. 初次入栈,最小值和入栈值相同,所以差值为0
    在这里插入图片描述
  2. 第二次入栈时,入栈0,与-2差值为0 - ( -2 ) = 2
    在这里插入图片描述
  3. 第3次入栈时,入-3,与-2的差值为 ( -3 ) - ( -2 ) = -1. 最小值更新为-3.我们发现如果遇到更小值,那么差值为负数,并且更新了最小值
    在这里插入图片描述
  4. 此时执行getMin()获取最小值,直接返回Min变量保存的-3即可
  5. 此时执行出栈操作,我们发现,栈顶元素为负数,说明他就是当前最小值,那么需要执行逆运算获取接下来的最小值。
  1. 获取时的式子是:当前值 - 最小值 = 入栈值,(-3) - (-2) = 1并令当前值-3成为新的最小值
  2. 则当前 , 需要出栈的元素值,就是当前最小值-3
  3. 而新的最小值需要逆运算得出,最小值 = 当前值(就是当前最小值-3) - 入栈值 = (-3) - (-1) = -2. 故,出栈后,新的最小值为-2
    在这里插入图片描述
  1. 此时执行top操作获取栈顶元素,也需要逆操作。
  1. 如果栈顶元素<=0说明,当前最小值就是栈顶元素
  2. 如果不是,那就是通过式子:入栈值 = 原来的值 - 最小值得到的
  3. 还原则需要:原来的值 = 入栈值+最小值 = 2 + (-2) = 0. 故当前栈顶元素为0.
  1. 此时执行getMin()操作,获取最小值,依然获取MIn保存的值-2即可。
代码

在这里插入图片描述

class MinStack {
    // 记录每个元素与【未压入】该元素时栈中最小元素的差值
    LinkedList<Long> stack;
    // 当前【已压入】栈中元素的最小值
    private long min;
    public MinStack() {
        stack = new LinkedList();//初始化栈
    }
    
    public void push(int val) {
        // 压入第一个元素
        if(stack.isEmpty()){//栈为空时
            min = val;//最小值就是当前值
            stack.addFirst(0L);//头插法,当前值和最小值相同,所以他俩的差值为0
            return;
        }
        // 栈不为空时,每次压入计算与min的差值后压入结果
        stack.push((long)val-min);
        // 更新min,保存更小的
        min = Math.min((long)val,min);
        // 上面两个语句是不能颠倒的!一定是先压入,在更新,因为min一定是当前栈中的最小值
    }
    
    public void pop() {
        long pop = stack.removeFirst();
        // 当弹出元素小于0时,说明弹出元素是当前栈中的最小值,要更新最小值
        if(pop<0){
            // 因为对于当前弹出的元素而言,计算压入栈中的值时,计算的是该元素与【未压入】该元素时
            // 栈中元素的最小值的差值,故弹出该元素后栈中的最小值就是未压入该元素时的最小值
            // 即当前元素的值(min)减去两者的差值
            long lastMin = min;
            min = lastMin - pop;
        }
        // 若大于等于0,不会对min有影响
    }
    
    public int top() {
        long peek = stack.peek();
        // 若当前栈顶小于等于0,说明最小值就是栈顶元素
        if(peek<=0) return (int)min;
        // 否则就是min+peek
        return (int)(min+peek);
    }
    
    public int getMin() {
        return (int)min;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1458072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Git】Gitbash使用ssh 上传本地项目到github

SSH Git上传项目到GitHub&#xff08;图文&#xff09;_git ssh上传github-CSDN博客 前提 ssh-keygen -t rsa -C “自己的github电子邮箱” 生成密钥&#xff0c;公钥保存到自己的github的ssh里 1.先创建一个仓库&#xff0c;复制ssh地址 git init git add . git commit -m …

机器学习之梯度下降法直观理解

形象化举例&#xff0c;由上图所示&#xff0c;假如最开始&#xff0c;我们在一座大山上的某处位置&#xff0c;因为到处都是陌生的不知道下山的路&#xff0c;所以只能摸索着根据直觉&#xff0c;走一步算一步。在此过程中&#xff0c;每走到一个位置的时候&#xff0c;都会求…

shell运行原理

前言 前一段时间由于身体的缘故和一些琐事&#xff0c;好久没有更新Linux的博文了。从本篇博文开始会接着以前的内容一直持续更新&#xff01; 本期类容介绍 为什么存在shell外壳&#xff1f; 什么是shell外壳&#xff1f; shell外壳是如何工作的&#xff1f; 一、为什么存在…

领域驱动设计(Domain Driven Design)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、场景和要求二、领域模型关键词1.领域2.子域3.通用语言4.限界上下文5.领域模型6.实体和值对象7.聚合根8.领域服务9.领域事件 总结 前言 Domain Driven Desi…

垂起固定翼无人机基础知识,垂起固定翼无人机应用前景,垂起固定翼无人机优缺点分析

无人机定义与类型 无人机&#xff0c;也称为无人驾驶飞行器&#xff0c;是一种无需人工直接操作的航空器。根据其用途、设计及技术特点&#xff0c;可以分为多种类型。垂起固定翼无人机是其中的一种&#xff0c;它具有垂直起降的能力并采用固定翼设计以提高飞行效率和稳定性。…

基于WOA优化的Bi-LSTM多输入时序回归预测(Matlab)鲸鱼算法优化双向长短期神经网络时序回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、算法介绍&#xff1a; 鲸鱼优化算法&#xff08;WOA&#xff09;&#xff1a; 双向长短期神经网络&#xff08;Bi-LSTM&#xff09;&#xff1a…

GC调优学习

一.常见工具P62P63 1.jstat 2.visualvm插件 3.Prometheus Grafana 4.GC日志 5.GC Viewer 6.GCeasy&#xff08;强推&#xff09; 二.常见的GC模式P64 三.GC调优 1.优化基础JVM参数P65 2.减少对象产生 看以前视频&#xff0c;内存泄露相关 3.垃圾回收器的选择P66 4.优化垃圾回…

数字孪生核心技术揭秘(一):渲染引擎

数字孪生最早是应用于大型装备制造业领域的一项革命性创新&#xff0c;通过搭建一个将制造流程全部进行整合的数字孪生生产系统&#xff0c;实现从产品设计、到生产计划、再到制造执行的全过程数字化。数字孪生概念与城市数字化管理结合之后&#xff0c;便诞生了“数字孪生城市…

解密短视频上火爆的“私董会”现象

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 最近“私董会”一词再一次上了热门&#xff0c;先是一夜暴火的商业博主dada管培生翻车暴雷&#xff0c;后面是三言财经、互联网大V纷纷发表了自己的看法。 国内领先的私董会服务机构通常每年的收费都在3万元起步。…

Kubernetes基础(二十二)-K8S的PV/PVC/StorageClass详解

1 概述 先来个一句话总结&#xff1a;PV、PVC是K8S用来做存储管理的资源对象&#xff0c;它们让存储资源的使用变得可控&#xff0c;从而保障系统的稳定性、可靠性。StorageClass则是为了减少人工的工作量而去自动化创建PV的组件。所有Pod使用存储只有一个原则&#xff1a;先规…

开源新手之邮件列表

很多老牌开源社区都使用邮件列表作为沟通的主要工具&#xff0c;比如Linux&#xff0c;Git&#xff0c;Apache等等&#xff0c;那么邮件列表是什么&#xff1f;又该怎么使用呢&#xff1f; 作为接触开源社区不久的新手&#xff0c;当然是求助程序员最好的朋友 google 了 什么是…

RK3588平台开发系列讲解(视频篇)ffmpeg 的移植

文章目录 一、ffmpeg 介绍二、ffmpeg 的组成三、ffmpeg 依赖库沉淀、分享、成长,让自己和他人都能有所收获!😄 📢ffmpeg 是一种多媒体音视频处理工具,具备视频采集功能、视频抓取图像、视频格式转换、给视频加水印并能将视频转化为流等诸多强大的功能。它采用 LGPL 或 G…

CF778A String Game 题解

文章目录 CF778A String Game 题解题面翻译Input DataOutput DataInput Sample 1Output Sample 1题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示算法&#xff1a;二分代码&#xff1a; CF778A String Game 题解 link 题面翻译 …

如何通过API在1688平台选品呢?

API接口&#xff08;Application Programming Interface&#xff09;是一种定义了软件组件之间交互的规范。它允许不同的软件系统之间进行通信和数据交换&#xff0c;使得开发者可以利用已有的功能和服务来构建自己的应用程序。 API接口可以分为不同的类型&#xff0c;包括Web…

微信小程序swiper 视频中间大,两边小,轮播滑到中间视频自动播放组件教程

静态效果&#xff1a; 进入下面小程序可以体验效果&#xff0c;点击底部 看剧 栏目 一、创建小程序组件 二、代码 1、WXML <view class"swiper-wrapper" style"background-image:url(/asset/image/hot-banner.jpg);background-size: 100% 100%;">…

Linux程序性能分析60秒+

Linux性能分析大师Brendan Gregg有一篇非常著名的博客&#xff0c;介绍在性能分析开始的60秒内&#xff0c;利用标准的Linux命令行工具&#xff0c;执行一次充分的性能检查&#xff0c;获得系统资源利用率和进程运行情况的整体概念&#xff0c;查看是否存在异常、评估饱和度。本…

Elasticsearch:什么是搜索引擎?

搜索引擎定义 搜索引擎是一种软件程序或系统&#xff0c;旨在帮助用户查找存储在互联网或特定数据库中的信息。 搜索引擎的工作原理是对各种来源的内容进行索引和编目&#xff0c;然后根据用户的搜索查询向用户提供相关结果列表。 搜索引擎对于希望快速有效地查找特定信息的用…

【漏洞复现】大华DSS城市安防系统文件读取漏洞

Nx01 产品简介 大华DSS数字监控系统是一个在通用安防视频监控系统基础上设计开发的系统&#xff0c;除了具有普通安防视频监控系统的实时监视、云台操作、录像回放、报警处理、设备治理等功能外&#xff0c;更注重用户使用的便利性。 Nx02 漏洞描述 大华城市安防监控系统平台管…

计算机网络-广域通信网

1.广域网概念和分类 什么是广域网&#xff1f; 广域网是指长距离跨地区的各种局域网、计算机、终端互联在一起&#xff0c;组成一个资源共享的通信网络。 广域网分为传统广域网和现代广域网。 传 统 广 域 网公共交换电话网PSTN公共数据网X.25帧中继网FR综合业务数据网ISDN…

GitHub仓库文件部署

目录 软件下载和安装 git创建仓库 Github仓库配置 git管理软件配置 Git管理 软件下载和安装 首先需要下载git&#xff0c;以及git管理软件&#xff0c;对其进行安装。 git创建仓库 首先需要创建仓库&#xff0c;在本地仓库文件夹cmd之后输入以下指令创建git仓库文件。 …