【初阶解法-数据结构】包含min函数的栈(代码+图示)

news2024/11/17 17:36:04

【数据结构】刷题-包含min函数的栈(代码+图示)-初阶解法

文章目录

  • 【数据结构】刷题-包含min函数的栈(代码+图示)-初阶解法
    • 题目
    • 提炼题目要求
    • 分析题目
    • 总结思路
    • 代码
    • 时间/空间复杂度
    • 进阶版

题目

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop、top 和 min 函数操作时,栈中一定有元素。

此栈包含的方法有:

push(value):将value压入栈中

pop():弹出栈顶元素

top():获取栈顶元素

min():获取栈中最小元素

数据范围:操作数量满足 0≤n≤300 ,输入的元素满足 ∣val∣≤10000

栈的各个操作的时间复杂度是 O(1) ,空间复杂度是O*(n)

提炼题目要求

题目核心要求

  • 实现push(value),pop(),top(),min()函数
  • 要求各个函数的时间复杂度均为O(1)
  • 空间复杂度为O(n)

分析题目

解决这类问题的关键是设计一个能够在O(1)时间内完成 pushpoptopmin 操作的数据结构。通常,我们会考虑 使用辅助栈或其他数据结构来维护额外的信息。

当我遇到这类问题时,我会考虑以下几个步骤:

  1. 使用辅助栈:
    • 我通常会考虑使用一个辅助栈来保存额外的信息,比如最小值。
    • 辅助栈可以在主栈的每个状态下都保存一些额外的信息,以便在O(1)时间内支持 min 操作。
  2. 考虑特殊情况:
    • 考虑空栈的情况,并确保代码对空栈的处理是正确的。
  3. 保持同步:
    • 在使用辅助栈或其他数据结构时,确保主栈和辅助数据结构之间保持同步,以防止出现不一致的情况。
  4. 复杂度分析:
    • 在实现解决方案后,分析代码的时间复杂度和空间复杂度,确保它们满足问题的要求。

举例来说,如果题目要求实现一个支持O(1)时间复杂度的 min 操作的栈,我可能会考虑使用辅助栈来保存每个状态下的最小值。在 push 操作中,我会在辅助栈中更新最小值;在 pop 操作中,我会同时弹出主栈和辅助栈的栈顶元素。这样就能够保持O(1)时间复杂度的 min 操作。


总结思路

下面是一种使用辅助栈的简单实现思路初阶

  1. 主栈 s1 用于正常的栈操作。
  2. 辅助栈 s2 用于存储每个状态下的最小值。

push 操作时:

  • 将元素压入主栈 s1
  • 检查辅助栈 s2 是否为空,或者新元素是否小于等于辅助栈的栈顶元素。如果是,将新元素也压入辅助栈 s2。否则,重复压入辅助栈的栈顶元素。

pop 操作时:

  • 分别从主栈 s1 和辅助栈 s2 弹出栈顶元素。

min 操作时:

  • 直接返回辅助栈 s2 的栈顶元素。

NOTE : 这样,辅助栈 s2 中的栈顶元素始终对应于主栈 s1 的当前最小值,而且由于每次 pushpop 操作都会同时更新两个栈,保持了两个栈的同步。这样,min 操作的时间复杂度是 O(1)。

如果对于push操作中的重复压入辅助栈的栈顶元素感到困惑,我将详细解释这背后的原因。

  • 当我们仅仅在push操作中实时监控辅助栈s2的栈顶元素是否一直保持是所有元素中的最小值时,这只是解决了问题的一半。因为栈中元素的变动不仅仅是由push操作引起的,我们还需要考虑pop操作。在弹出元素的同时,主栈s1中的元素也发生了变化。因此,为了确保s2能够实时监控到pop操作,我们必须同时在主栈s1进行pop操作的时候,保证辅助栈s2也要同时更新以进行pop操作。那么问题来了,如何在s2中保证有元素可以弹出,并且不会改变栈顶元素一直是最小值呢?
    • 解决这个问题的方法是,在入栈push的时候,如果待插入的元素比最小值大,我们就将当前最小值重复入栈。这样就保证了每当主栈s1入栈一个元素时,辅助栈s2也会入栈一个元素。这种做法的好处在于,之后无论何时进行出栈pop操作,我们都能够确保s2中有元素可以弹出。而且,一旦成功弹出元素,s2的栈顶元素仍然保持是最小值!
    • 如下图演示

image-20231204215629193

(同步)正常的出栈操作

image-20231204215913351

(未同步)异常的出栈操作

image-20231204220235603

代码

import java.util.*;
import java.util.Stack;


/*
含有min函数的栈

这个题目需要我们自己实现栈的基本的结构
 */

public class Solution{

    //这个栈1是我们的主要的栈
    Stack<Integer> stack1 = new Stack<>();

//这个栈2 是我们专门用来保存最小值的栈
    Stack<Integer> stack2 = new Stack<>();

    public void push(int node) {

        //准备一个辅助栈,这个栈必须在push方法中,因为这样我们就可以直接就保证min函数里面的栈中保存的一定是最小的值
        //所以我们就只需要在插入元素的时候就进行筛查
        stack1.push(node);
       
        if(stack2.empty()||node<stack2.peek()){
            stack2.push(node);
        }else{
            stack2.push(stack2.peek());
        }
    }

    public void pop() {
        stack1.pop();
        stack2.pop();
    }

    public int top() {
        return stack1.peek();

    }

    public int min() {
        return stack2.peek();
    }
}

时间/空间复杂度


时间复杂度分析

push(int node):

  • stack1.push(node):将元素推入主栈 stack1,O(1)。
  • 判断并更新最小值:
    • 如果 stack2 为空,或者新元素 node 小于 stack2 的栈顶元素,执行 stack2.push(node),O(1)。
    • 否则,执行 stack2.push(stack2.peek()),O(1)。
  • 因此,整体的时间复杂度为 O(1)。

pop():

  • 同时从 stack1stack2 弹出栈顶元素,都是O(1)的操作。
  • 因此,整体的时间复杂度为 O(1)。

top():

  • 直接返回 stack1 的栈顶元素,O(1)的操作。
  • 因此,整体的时间复杂度为 O(1)。

min():

  • 直接返回 stack2 的栈顶元素,O(1)的操作。
  • 因此,整体的时间复杂度为 O(1)。

空间复杂度分析

  • 主栈 stack1 和辅助栈 stack2 都需要额外的空间来存储元素,因此空间复杂度是 O(n),其中 n 是推入栈的元素数量。

进阶版

进阶版 -> 使用差值:在一些情况下,我们可以使用差值来存储元素与当前状态下的最小值的关系,从而降低空间复杂度。(我会在下一篇博客里面讲的)

image-20231129200715576

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

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

相关文章

SpringBoot——嵌入式 Servlet容器

一、如何定制和修改Servlet容器的相关配置 前言&#xff1a; SpringBoot在Web环境下&#xff0c;默认使用的是Tomact作为嵌入式的Servlet容器&#xff1b; 【1】修改和server相关的配置&#xff08;ServerProperties实现了EmbeddedServletContainerCustomizer&#xff09;例如…

华为交换机,配置攻击防范示例

攻击防范简介 定义 攻击防范是一种重要的网络安全特性。它通过分析上送CPU处理的报文的内容和行为&#xff0c;判断报文是否具有攻击特性&#xff0c;并配置对具有攻击特性的报文执行一定的防范措施。 攻击防范主要分为畸形报文攻击防范、分片报文攻击防范和泛洪攻击防范。 …

7. 系统信息与系统资源

7. 系统信息与系统资源 1. 系统信息1.1 系统标识 uname()1.2 sysinfo()1.3 gethostname()1.4 sysconf() 2. 时间、日期2.1 Linux 系统中的时间2.1.1 Linux 怎么记录时间2.1.2 jiffies 的引入 2.2 获取时间 time/gettimeofday2.2.1 time()2.2.2 gettimeofday() 2.3 时间转换函数…

MySQL笔记-第02章_MySQL环境搭建

视频链接&#xff1a;【MySQL数据库入门到大牛&#xff0c;mysql安装到优化&#xff0c;百科全书级&#xff0c;全网天花板】 文章目录 第02章_MySQL环境搭建1. MySQL的卸载步骤1&#xff1a;停止MySQL服务步骤2&#xff1a;软件的卸载步骤3&#xff1a;残余文件的清理步骤4&am…

【Cesium】实现卷帘对比

一、创建滑块 <style>import url(../Build/CesiumUnminified/Widgets/widgets.css);import url(./Sandcastle/templates/bucket.css);#slider {position: absolute;left: 50%;top: 0px;background-color: #d3d3d3;width: 5px;height: 100%;z-index: 9999;}#slider:hover…

leetcode 876.链表的中间结点

补充上次的环形链表没细讲的快慢指针&#xff08;这三道题现在可以连起来看&#xff09;&#xff0c;希望对你做题思路有帮助 876.链表的中间结点 题目 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结…

机械学习概述

1.1 什么是机器学习 1.1.1 机器的学习能力 1997年5月11日&#xff0c;一台名为“深蓝”的超级电脑战胜国际象棋名家卡斯帕罗夫。20世纪末的一场人机大战终于以计算机的微弱优势取胜。 2016年3月&#xff0c;阿尔法围棋程序&#xff08;AlphaGo&#xff09;挑战世界围棋冠军李…

windows11 调整鼠标灵敏度方法

首先 我们打开电脑设置 或者在 此电脑/此计算机/我的电脑 右击选择属性 然后 有的电脑 左侧菜单中 直接就有 设备 然后在设备中直接就可以找到 鼠标 选项 调整光标速度即可 如果操作系统和我的一样 可以直接搜索鼠标 然后 选择 鼠标设置 然后 调整上面的鼠标指针速度即可

锁策略之干货分享,确定不进来看看吗?️️️

&#x1f308;&#x1f308;&#x1f308;今天给大家分享的是关于锁策略方面的基础知识。 清风的CSDN博客 &#x1f6e9;️&#x1f6e9;️&#x1f6e9;️希望我的文章能对你有所帮助&#xff0c;有不足的地方还请各位看官多多指教&#xff0c;大家一起学习交流&#xff01; …

基于stm32的LCD1602与无线蓝牙温湿度显示

这一篇博客是为了实现温湿度的显示&#xff0c;温湿度传感器将数据穿给单片机&#xff0c;单片机又把数据送给LCD1602和蓝牙&#xff0c;让温度和湿度可以再LCD1602显示屏和手机上显示&#xff0c;它的执行逻辑和C51那里基本一样&#xff0c;就是要修改程序&#xff0c;在程序上…

选择排序、插入排序、希尔排序

1.选择排序 算法描述 将数组分为两个子集&#xff0c;排序的和未排序的&#xff0c;每一轮从未排序的子集中选出最小的元素&#xff0c;放入排序子集 重复以上步骤&#xff0c;直到整个数组有序 选择排序呢&#xff0c;就是首先在循环中&#xff0c;找到数组中最小的元素。在…

基恩士软件的基本操作(六,KV脚本的使用)

目录 什么是KV脚本&#xff1f; KV脚本有什么用&#xff1f; 怎么使用KV脚本&#xff08;脚本不能与梯形图并联使用&#xff09;&#xff1f; 插入框脚本&#xff08;CtrlB&#xff09; 插入域脚本&#xff08;CtrlR&#xff09; 区别 脚本语句&#xff08;.T是字符串类…

详解原生Spring当中的事务

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…

Redis实战篇笔记(最终篇)

Redis实战篇笔记&#xff08;七&#xff09; 文章目录 Redis实战篇笔记&#xff08;七&#xff09;前言达人探店发布和查看探店笔记点赞点赞排行榜 好友关注关注和取关共同关注关注推送关注推荐的实现 总结 前言 本系列文章是Redis实战篇笔记的最后一篇&#xff0c;那么到这里…

界面组件DevExpress Reporting v23.1新版亮点 - UX功能增强

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表 界面组件DevExpress Reporting v23.1已于前段时间…

探讨Unity中的动画融合技术(BlendTree)

动画在游戏和虚拟现实应用中扮演着关键的角色&#xff0c;而动画融合技术则是使角色动作更加流畅和逼真的核心。在Unity引擎中&#xff0c;我们可以使用动画混合树&#xff08;Blend Trees&#xff09;来实现这一目标。本篇技术博客将深入讨论动画融合技术的实现原理、在Unity中…

C++ 指针详解

目录 一、指针概述 指针的定义 指针的大小 指针的解引用 野指针 指针未初始化 指针越界访问 指针运算 二级指针 指针与数组 二、字符指针 三、指针数组 四、数组指针 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 指针与数组 一维数组 字符数组…

FreeRTOS调度器启动过程分析

目录 引出思考 vTaskStartScheduler()启动任务调度器 xPortStartScheduler()函数 FreeRTOS启动第一个任务 vPortSVCHandler()函数 总结 引出思考 首先想象一下如何启动第一个任务&#xff1f; 假设我们要启动的第一个任务是任务A&#xff0c;那么就需要将任务A的寄存器值…

腾讯云手动下发指令到设备-用于设备调试

打开腾讯云API Explorer&#xff0c;Publish Msg https://console.cloud.tencent.com/api/explorer?Productiotcloud&Version2021-04-08&ActionPublishMessagehttps://console.cloud.tencent.com/api/explorer?Productiotcloud&Version2021-04-08&ActionPub…

【模电】设置静态工作点的必要性

设置静态工作点的必要性 静态工作点为什么要设置静态工作点 静态工作点 在放大电路中&#xff0c;当有信号输入时&#xff0c;交流量与直流量共存。将输入信号为零、即直流电源单独作用时晶体管的基极电流 I B I\tiny B IB、集电极电流 I C I\tiny C IC、b - e间电压 U B E U\t…