栈的实现及相关OJ题

news2024/11/29 6:32:07

🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!

人生格言:当你的才华撑不起你的野心的时候,你就应该静下心来学习!

欢迎志同道合的朋友一起加油喔🦾🦾🦾
目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个🐒嘿嘿
谢谢你这么帅气美丽还给我点赞!比个心


目录

1. 什么是栈?(Stack)

2. 栈的使用

3. 模拟实现一个栈

3.1 构造方法和成员属性

3.2 push 方法

3.3 pop 方法

3.4 peek 方法

3.5 empty 方法

4.栈相关的OJ题

   4.1 有效的括号

  4.2 栈的压入弹出序列

  4.3 逆波兰(后缀)表达式求值

  4.4 最小栈



1. 什么是栈?(Stack)

 栈是一种数据结构,是操作受限制的线性表(先进后出),它只能在固定的一端进行插入和删除操作,进行数据插入和删除的一端为栈顶,另一端为栈底,按存储方式分为顺序栈(更好实现)和链式栈。

压栈:栈的插入操作叫做进栈/压栈/入栈。入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。

2. 栈的使用

方法功能说明
Stack()构造一个空栈
E push(E e)将e入栈并返回e
E pop()将栈顶元素出栈并返回
E peek()获取栈顶元素
int size()获取栈中有效元素的个数
boolean empty()检测栈是否为空

  ●顺序栈:Deque接口+实现类ArrayDeque

Deque<Integer> deque = new ArrayDeque<>();//顺序栈

 ●链式栈:Deque接口+实现类LinkedList

Deque<Integer> deque1 = new LinkedList<>();//链式栈

   栈的使用建议使用上面两种方式,不建议使用Stack

3. 模拟实现一个栈

3.1 构造方法和成员属性

public class MyStack {
    private int[] elem; //存放数据的数组
    private int size; //有效元素个数
    private static final int DEFAULT_CAPACITY = 10; //约定好的默认容量
 
    public MyStack() {
        this.elem = new int[DEFAULT_CAPACITY];
        this.size = 0;
    }
}

有了顺序表和链表的学习,再次学习栈是很轻松的,但是在源码中,开辟空间是在 push 中开辟的,跟顺序表类似的。

3.2 push 方法

// 压栈
public int push(int data) {
    // 判断是否需要增容
    if (this.size == this.elem.length) {
        this.elem = Arrays.copyOf(this.elem, this.size * 2);
    }
    // 压栈只能往栈顶压栈
    this.elem[this.size++] = data;
    return data;
}

在实现push方法要注意,栈扩容的问题,因为我们底层使用的是数组,所以可以用 Arrays.copyOf方法进行扩容。 

3.3 pop 方法

// 出栈
public int pop() {
    // 判断栈是否为null
    if (this.size == 0) {
        throw new MyStackEmptyException("栈为空!");// 自定义异常
    }
    return this.elem[--this.size];
}

在出栈方法中,如果栈为null的情况是不能进行出栈的,也就是有效元素个数size为0的情况,这里博主是直接抛出了一个自定义异常。在返回值的地方也要注意,出栈后栈的元素会减少一个,但我们只需要设置有效数据减一个即可,就像计算机中的删除一样,本质是将数据设置成无效,有新的数据可以直接覆盖。

3.4 peek 方法

// 查看栈顶元素
public int peek() {
    // 判断栈是否为null
    if (this.size == 0) {
        throw new MyStackEmptyException("栈为空!"); //自定义异常
    }
    return this.elem[this.size - 1];
}

peek方法与pop方法相差无几,需要注意的是在返回栈顶元素的时候不要使有效数据个数减少了就像。

3.5 empty 方法

// 判断栈是否为空
public boolean empty() {
    return this.size == 0;
}

4.栈相关的OJ题

   4.1 有效的括号

        ●题目展示

       ● 写题链接:20. 有效的括号 - 力扣(LeetCode)

       ● 写题思路:

           1) 新建一个栈存左括号,得到对应右括号出左括号,这次匹配成功,继续匹配

           2) 只要左括号的栈为空,且给定字符串还没遍历完,那就代表右括号多了

           3) 给定字符串遍历完了,但是存左括号的栈还有剩余的左括号,那么就是左括号多了

           4) 只要给定字符串遍历完毕,且存左括号的栈无剩余,则为有效括号。

        ● 图示

       ● 实现代码:

class Solution {
    public boolean isValid(String s) {
       Deque<Character> leftStack = new ArrayDeque();
       for(int i = 0; i < s.length(); i++) {
           char ch = s.charAt(i);
           if(ch == '(' || ch == '[' || ch == '{') {
               leftStack.push(ch);
           }else {
               //如果栈中无左括号,又得到了一个右括号,则无效
               if(leftStack.isEmpty()) { //多余的右括号
                   return false;
               }
               //ch为字符串中得到的右括号,ch2为栈中的左括号
               char ch2 = leftStack.peek();
               if(ch == ')' && ch2 == '(' || ch == ']' && ch2 == '[' || ch == '}' && ch2 == '{') {
                   //出栈
                   leftStack.pop();
               }else {
                   return false;//不匹配
               }
           }
       }
       if(!leftStack.isEmpty()) { //还有多余的左括号
           return false;
       }
       return true;
    }
}

  4.2 栈的压入弹出序列

        ● 题目展示


       ● 写题链接:栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com)

       ● 写题思路:

           1) 新建一个栈,根据给定的出栈序列依次进行匹配。

           2) 只要不等于出栈序列的数字,就一直遍历入栈序列入栈

           3) 等于出栈序列的数字后,直接出栈,只要等于出栈序列的数字,该栈就一直出栈,直到不等于结束出栈,继续遍历给定的入栈序列进行入栈。

           4) 重复该操作直到遍历完入栈序列,最后这个栈如果为空,则匹配成功,反之则匹配失败

        ● 图示

         ● 实现代码:

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
      Stack<Integer> stack = new Stack<>();
          int j = 0;
          for(int i = 0;i < n;i++){
            stack.push(pushA[j]);
            //此处用equals是因为Integer值的取值范围在-128~127
            while(j < pop.length && (stack.isEmpty()||stack.peek().equals(popA[i])){
                stack.pop();
                j++;
            }
        return stack.empty();
    }
}

  4.3 逆波兰(后缀)表达式求值

         ● 题目展示


       ● 写题链接:150. 逆波兰表达式求值 - 力扣(LeetCode)

       ● 写题思路:

          1) 准备中间栈遍历给定后缀表达式,遇到操作数则入中间栈

          2) 遇到操作符则出栈两个操作数进行运算,并将运算结果入栈

          3) 直到后缀表达式遍历完毕,栈中最后一个元素值则为计算结果

        ● 知识普及

         在讲解这个题之前给大家普及一点知识,我们平时的算术表达式中,运算符总是出现在两个操作数之间,例如 5 * (7 - 2 * 3) + 8 / 2 ,这种形式叫做中缀表达式,而我们的逆波兰表达式又叫后缀表达式,那什么是后缀表达式呢???

我们把中缀表达式的运算符移动到自己所在的括号的右括号的右边,然后再去括号,这就是逆波兰表达式,,,那这个东西该怎么计算呢??? 

       ● 实现代码:

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> stack = new ArrayDeque<Integer>(); //存操作数
        for(int i = 0; i < tokens.length; i++) {
            String ch = tokens[i];
            if(!isOperators(ch)) {
                stack.push(Integer.parseInt(ch));
            }else {
                int num1 = stack.pop();//出两个操作数
                int num2 = stack.pop();
                int result = 0; //计算结果  
                switch(ch) {
                    case "+":
                    result = num1 +num2;
                    break;
                    case "-":
                    result = num2 - num1;
                    break;
                    case "*":
                    result = num1 * num2;
                    break;
                    case "/":
                    result = num2 / num1;
                    break;
                }
                //结果入栈
                stack.push(result);
            }
        }
        return stack.pop();
    }
 
    //判断是否为操作符
    public boolean isOperators(String s) {
        return s.equals("+") || s.equals("*") || s.equals("-") || s.equals("/");
    }
}

  4.4 最小栈

          ● 题目展示

         ● 写题链接:力扣

         ● 写题思路:题目的目的是想让我们在O(1)时间复杂度内拿到栈的最小值,所以这里我们不能去遍历栈,而是需要用到两个栈,下面用画图的形式分析一下如何做到:

         ● 实现代码:

class MinStack {
    private Stack<Integer> stack1;
    private Stack<Integer> MinStack;
 
    public MinStack() {
        stack1 = new Stack<>();
        MinStack = new Stack<>();
    }
 
    public void push(int val) {
        stack1.push(val);
        if(MinStack.empty()) {
            MinStack.push(val);
        } else {
            if(val <= MinStack.peek()) {
                MinStack.push(val);
            }
        }
    }
    //题目规定了栈不为空,所以这里没判断
    public void pop() {
        int tmp = stack1.pop();
        if(tmp == MinStack.peek()) {
            MinStack.pop();
        }
    }
    //题目规定了栈不为空
    public int top() {
        return stack1.peek();
    }
 
    public int getMin() {
        return MinStack.peek();
    }
}

5. 栈,虚拟机栈,栈帧的区别

栈:一种后进先出的数据结构,继承自Vector

虚拟机栈:具有特殊作用的一块内存空间。栈区:是线程私有的,存放的是函数调用相关信息,主要是栈帧,它是按照数据结构中栈的特性来实现的

栈帧:一种结构,与函数调用相关。内部:局部变量表,操作数栈。每个方法运行时JVM会创建一个栈帧,然后将栈帧压到虚拟机栈中,调用结束时,该方法对应的栈帧会从虚拟机栈中出栈。

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

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

相关文章

28岁,他是如何成为上市公司测试总监的

现在的大环境下&#xff0c;各行各业都开始内卷起来&#xff0c;测试也不例外&#xff0c;企业要求也越来越高&#xff0c;“会代码”逐渐成为测试工程师的一个标签。你要想拿到一个不错的薪资&#xff0c;必不可少的一个技能—自动化测试&#xff0c;自动化测试难吗&#xff1…

Oracle集合查询详解加练习题

#集合查询 概念&#xff1a;将不同的数据集合&#xff08;SQL查询语句&#xff09;按照集合的规则&#xff0c;拼接一个临时的&#xff0c;新的数据集合&#xff08;表&#xff09; 1.集合&#xff1a;并集、交集、差集 并集 union all 语法&#xff1a;select column1,COLUM…

「MongoDB」时序数据库和MongoDB第二部分-模式设计最佳实践

在上一篇博客文章时间序列数据与MongoDB&#xff1a;第一部分-简介中&#xff0c;我们介绍了时间序列数据的概念&#xff0c;然后介绍了一些可以用于帮助收集时间序列应用程序需求的发现问题。对这些问题的回答有助于指导支持大容量生产应用程序部署所需的模式和MongoDB数据库配…

基于深度学习PaddleOcr身份证识别

之前使用opencv机械学习处理图片&#xff0c;使用Testseract-OCR进行身份证和姓名识别&#xff0c;发现受背景图片的影响比较大&#xff0c;转PaddleOcr&#xff0c;识别成功率能达到使用要求。 PaddleOcr官网地址&#xff1a;飞桨PaddlePaddle-源于产业实践的开源深度学习平台…

Python爬虫-某跨境电商(AM)搜索热词

前言 本文是该专栏的第42篇,后面会持续分享python爬虫干货知识,记得关注。 关于某跨境电商(AM),本专栏前面有单独详细介绍过,获取配送地的cookie信息以及商品库存数据,感兴趣的同学可往前翻阅。 1. python爬虫|爬取某跨境电商AM的商品库存数据(Selenium实战) 2. Seleni…

偶数科技发布实时湖仓数据平台 Skylab 5.0

2023 年 4 月 11 日&#xff0c; 偶数发布了最新的实时湖仓数据平台 Skylab 5.0&#xff0c;平台各个组件进行了全面升级。新版 Skylab 的发布标志着偶数科技具有从数据存储、计算、管理到分析、应用和 AI 能力的完整的数据管理生态闭环&#xff0c;帮助用户实现批流一体、实时…

贴完车衣开车就走?

贴完车衣之后&#xff0c;你以为直接开走就好了吗&#xff1f; 大错特错&#xff01;&#xff01;&#xff01; 正确流程&#xff0c;记得收藏起来&#xff01; 1&#xff1a;膜开箱&#xff1a;这个当场开箱&#xff0c;防止偷梁换柱 2&#xff1a;装贴过程&#xff1a;确认施…

损失函数(Loss Function)一文详解-分类问题常见损失函数Python代码实现+计算原理解析

目录 前言 一、损失函数概述 二、损失函数分类 1.分类问题的损失函数 1.交叉熵损失函数&#xff08;Cross Entropy Loss&#xff09; 2.Hinge损失函数 3.余弦相似度损失函数&#xff08;Cosine Similarity Loss&#xff09; 4.指数损失函数&#xff08;Exponential Los…

Next.js Polygon, Solidity,The Graph,IPFS,Hardhat web3博客系统

参考 源文档The Complete Guide to Full Stack Web3 Development - DEV Community 源码&#xff0c;源文章里的github项目无法直接运行&#xff0c;经过修改后可mac中可用GitHub - daocodedao/web3-blog: https://linzhji.blog.csdn.net/article/details/130125634 框架 博客…

python pandas数据处理excel、csv列转行、行转列(具体示例)

一、数据处理需求 对Excel或CSV格式的数据,我们经常都是使用pandas库读取后转为DataFrame进行处理。有的时候我们需要对其中的数据进行行列转换,但是不是简单的行列转换,因为数据中有重复的数据属性。比如我们的数据在Excel中的格式如下: 那么,我们如何将上面的数据格式转…

2023爱分析·商业智能应用解决方案市场厂商评估报告:数聚股份

目录 1. 研究范围定义 2. 商业智能应用解决方案市场分析 3. 厂商评估&#xff1a;数聚股份 4. 入选证书 1. 研究范围定义 商业智能&#xff08;BI&#xff09;是在实现数据集成和统一管理的基础上&#xff0c;利用数据存储和处理、分析与展示等技术&#xff0c;满足企…

Java多线程案例-Java多线程(3)

各位观众老爷们, 创作不易, 多多支持&#x1f636;‍&#x1f32b;️&#x1f64f;&#x1f618; 字数11223, 时间:2023年4月16日11:19:58 状态: 精神恍恍惚惚, 想打游戏&#x1f975; 目录(点击传送) 单例模式 饿汉模式 懒汉模式 单线程版 多线程版 阻塞队列 什么是阻塞队…

助力工业物联网,工业大数据之ODS层及DWD层建表语法【七】

文章目录ODS层及DWD层构建01&#xff1a;课程回顾02&#xff1a;课程目标03&#xff1a;数仓分层回顾04&#xff1a;Hive建表语法05&#xff1a;Avro建表语法ODS层及DWD层构建 01&#xff1a;课程回顾 一站制造项目的数仓设计为几层以及每一层的功能是什么&#xff1f; ODS&am…

Pytorch-gpu的安装

1.先安装cuda和cudnn 推荐安装cuda11.3和cuda10.2&#xff0c;因为这两个版本用的多。 安装教程可以看我的另一篇文章&#xff1a; cuda和cudnn安装教程 2.安装对应版本的Pytorch Pytorch的版本需要和cuda的版本相对应。具体对应关系可以去官网查看。这里先附上一张对应关系…

openpnp - 顶部相机 - 辅助光(环形灯)的电路原理图

文章目录openpnp - 顶部相机 - 辅助光(环形灯)的电路原理图概述ENDopenpnp - 顶部相机 - 辅助光(环形灯)的电路原理图 概述 同学帮我做的简易灯板设计不太合理, 发热量极大. 想看看商用的环形灯电路啥样的, 如果有可能, 自己做块灯板, 塞进商用环形灯外壳中. 拆解了一个环形灯…

数据库备份

数据库备份&#xff0c;恢复实操 策略一&#xff1a;&#xff08;文件系统备份工具 cp&#xff09;&#xff08;适合小型数据库&#xff0c;是最可靠的&#xff09; 1、停止MySQL服务器。 2、直接复制整个数据库目录。注意&#xff1a;使用这种方法最好还原到相同版本服务器中&…

【图像分类】【深度学习】ViT算法Pytorch代码讲解

【图像分类】【深度学习】ViT算法Pytorch代码讲解 文章目录【图像分类】【深度学习】ViT算法Pytorch代码讲解前言ViT(Vision Transformer)讲解patch embeddingpositional embeddingTransformer EncoderEncoder BlockMulti-head attentionMLP Head完整代码总结前言 ViT是由谷歌…

Spring Boot+Vue实现Socket通知推送

目录 Spring Boot端 第一步&#xff0c;引入依赖 第二步&#xff0c;创建WebSocket配置类 第三步&#xff0c;创建WebSocket服务 第四步&#xff0c;创建Controller进行发送测试 Vue端 第一步&#xff0c;创建连接工具类 第二步&#xff0c;建立连接 ​编辑 第三步&a…

xxl-job-2.3.1 本地编译jar包并部署

参考网上其他文章&#xff0c;总结步骤 一、官网地址 分布式任务调度平台XXL-JOB 二、源码地址 github&#xff1a; GitHub - xuxueli/xxl-job: A distributed task scheduling framework.&#xff08;分布式任务调度平台XXL-JOB&#xff09; gitee: xxl-job: 一个分布…

k8s v1.26.2 安装部署步骤

准备 开通端口 master需要开通的端口: TCP: 6443 2379 2380 10250 10259 10257 ,10250 30000~30010(应用) node需要开通的端口: TCP: 10250 30000~30010(应用) master加端口 firewall-cmd --permanent --add-port6443/tcp firewall-cmd --permanent --add-port2379/tcp fir…