【数据结构练习题】栈——1.括号匹配 2.逆波兰表达式求值 3.出栈入栈次序匹配 4.最小栈

news2024/11/19 22:43:11

在这里插入图片描述
♥♥♥♥♥个人主页♥♥♥♥♥
♥♥♥♥♥数据结构练习题总结专栏♥♥♥♥♥

文件目录

  • 前言
    • 1.括号匹配
    • 1.1问题描述
    • 1.2解题思路
    • 1.3画图解释
    • 1.4代码实现
      • 2.逆波兰表达式求值
    • 2.1问题描述
    • 2.2解题思路
    • 2.3画图解释
    • 2.4代码解释
        • 3.出栈入栈次序匹配
    • 3.1问题描述
    • 3.2思路分析
    • 3.3画图解释
    • 3.4代码实现
          • 4.最小栈
    • 4.1问题描述
    • 4.2思路分析
    • 4.3画图分析
    • 4.4代码实现

前言

在学习数据结构的过程中遇到了各种各样类型的题目,我在解答这些题目的时候收获了不少,所以我想开设一个专栏来分享我平时做题的收获,在我分享的题中我采用三步法来阐述,希望大家可以在我的文章有收获,并且能够在评论区中积极讨论更多的解题方法。

1.括号匹配

1.1问题描述

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
1.左括号必须用相同类型的右括号闭合。
2.左括号必须以正确的顺序闭合。
3.每个右括号都有一个对应的相同类型的左括号

1.2解题思路

大主题:我们先遍历这个字符串,在遇到左括号就进行压栈,遇到右括号则出栈并与左括号匹配,在这会出现两种情况:
1.如果不匹配,则直接返回false。
2.如果匹配,则可以继续去遍历这个字符串。
特殊情况:
1.当遍历完字符串,发现栈中还有元素,则可以直接返回false。
2.当栈中的元素已经全部被弹出,发现字符串没有被遍历完,也直接返回false。

1.3画图解释

1.大主题:
在这里插入图片描述
2.特殊情况:
在这里插入图片描述

1.4代码实现

public class ParenMatch {
    Stack<Character> stack = new Stack<>();
    public boolean isValid(String str) {
        //1.遍历这个数组
        for (int i = 0; i < str.length(); i++) {
            //2.判断是左括号还是右括号
            char ch = str.charAt(i);
            //2.1左括号
            if(ch == '(' || ch == '[' || ch == '{' ) {
                //压栈
                stack.push(ch);
            }
            //2.2右括号 看栈中是否为空,为空直接返回flase 不为空判断左右括号是否匹配。
             else {
                //2.2.1栈中不为空
                if(!stack.empty()) {
                    char ch1 = stack.peek();//ch1是左括号。
                    //判断括号是否匹配
                    if(ch == ')' && ch1 == '(' || ch == ']' && ch1 == '[' || ch == '}' && ch1 == '{') {
                        stack.pop();
                    }
                    else {
                        return false;
                    }
                }
                //2.2.2栈中为空
                else {
                    return false;
                }
            }
        }
        //当数组遍历完之后,判断栈中是否空。
        return stack.empty();
    }

    public static void main(String[] args) {
        String str = "{()}";
        ParenMatch parenMatch = new ParenMatch();
        System.out.println(parenMatch.isValid(str));
    }
}

2.逆波兰表达式求值

2.1问题描述

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
有效的算符为 ‘+’、‘-’、‘*’ 和 ‘/’ 。
每个操作数(运算对象)都可以是一个整数或者另一个表达式。
两个整数之间的除法总是 向零截断 。
表达式中不含除零运算。
输入是一个根据逆波兰表示法表示的算术表达式。
答案及所有中间计算结果可以用 32 位 整数表示。

2.2解题思路

在解决这个问题,我先解释什么叫逆波兰表达式,其实它有个更好理解的一个名字叫后缀表达式,我们既然提到了后缀表达式,那估计也有一些人不知道后缀表达式是什么?那我们就需要引出中缀表达式来了解后缀表达式。
其实中缀表达式就是我们平时经常可以见到的一个表达式,它就是将运算符放在数字之间的一种表达式如:a+(b+c)+d*(e+f)这种类型的就叫中缀表达式,而后缀表达式其实就是将运算符放在数字的后面。我就用a+(b+c)+d*(e+f)这个来打比方,将它转化为后缀表达式。
中缀表达式转后缀表达式分三步:
第一步:加括号,从左到右先乘除后加减去加括号。
在这里插入图片描述
第二步:将运算符移到每个对应括号的外面
在这里插入图片描述
第三步:再将所有的括号全部删除,得到的就是后缀表达式
在这里插入图片描述
既然得到了后缀表达式,那我们运用栈来求这个表达式的值。
我们先将这个表达式看作一个字符串,然后我们再采用遍历的方法去一个一个的去遍历这个字符串,我采取的规则是遇到除运算符的任何元素压入栈中,遇到运算符则从栈中弹出两个元素,分别放在运算符的右侧和左侧(这里的左右很重要,因为运算符如果是除法或者减法,运算符的左右侧元素不同那么结果是不一样)得到的结果压入栈中,直到字符串遍历完之后,最后留在栈中的值就是这个表达式的值。

2.3画图解释

在这里插入图片描述

2.4代码解释

public class evalRPN {
    String[] tokens = {"2","1","+","3","*"};
    Stack<Integer> stack = new Stack<>();
    public int  ergodic() {
        //遍历这个数组
        for (int i = 0; i < tokens.length; i++) {
            //判断字符串是否为运算符字符串
            String str = tokens[i];
            if(!isOperator(str)) {
                //字符串为数字,说明将这个字符串数字先转化为数字再压入栈中
                int ret = Integer.valueOf(str);
                stack.push(ret);
            }
            else {
                //字符串为运算符
                int rightNum = stack.pop();
                int leftNum = stack.pop();
                switch (str) {
                    case "+":
                        stack.push(leftNum+rightNum);
                        break;
                    case "-":
                        stack.push(leftNum-rightNum);
                        break;
                    case "*":
                        stack.push(leftNum*rightNum);
                        break;
                    case "/":
                        stack.push(leftNum/rightNum);
                        break;
                }
            }
        }
        return stack.pop();
    }
    private boolean isOperator(String str) {
        if(str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/") ) {
            return true;
        }
        return false;
    }
    public static void main(String[] args) {
        evalRPN evalRPN = new evalRPN();
        System.out.println(evalRPN.ergodic());
    }
}

3.出栈入栈次序匹配

3.1问题描述

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

3.2思路分析

1.先去遍历第一个数组,每遍历到数组每一个元素先与压入栈中再看栈顶元素与另一个数组的第一个元素进行比较。
2.相同则弹出,并且第二个数组往后遍历反之第一个数组继续遍历并且压入栈中。
3.直到栈为空或者第一个数组遍历完。

3.3画图解释

在这里插入图片描述

3.4代码实现

public class PushPopMatch {
    Stack<Integer> stack = new Stack<>();
    public boolean IsPopOrder (int[] pushV, int[] popV) {
        int j =0;
        for (int i = 0; i < pushV.length; i++) {
            //1.压入栈中
            stack.push(pushV[i]);
            //2.将栈顶元素与popV数组比较,相同则弹出并且j++,反之继续压栈。
            //当这个条件stack.peek() == popV[j]出来了,你需要确保栈不能为空并且数组不能越界。
            while(j<popV.length &&!stack.empty() && stack.peek() == popV[j]) {
                stack.pop();
                j++;
            }
        }
        return stack.empty();
    }

    public static void main(String[] args) {
        int[] pushA = {1,2,3,4,5};
        int[] popA = {4,5,3,2,1};
        PushPopMatch pushPopMatch = new PushPopMatch();
        System.out.println(pushPopMatch.IsPopOrder(pushA, popA));
    }
}

4.最小栈

4.1问题描述

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。

4.2思路分析

我们先想一想,一个栈可以完成这个目标吗?,明显的是不能满足时间复杂度,所以我们需要两个栈来解决这个问题,我们创建一个普通栈和一个最小栈。
1.实现push操作:普通栈每一个元素都需要压栈,但最小栈有两种情况:
情况1:最小栈是空栈,那么第一个元素直接压入最小栈
情况2:最小栈不是空栈,则需要将压栈的元素与最小栈的栈顶元素进行比较,当满足压栈元素<=最小栈栈顶元素则压栈
2. 实现pop操作:普通栈每一个元素都可以出栈,但最小栈有两种情况:
情况1:普通栈出栈的元素与最小栈的栈顶元素相同则都弹出
情况2:普通栈出栈的元素与最小栈的栈顶元素不相同,则普通栈弹出,最小栈不要弹出。
3.实现top操作:直接弹出普通栈的栈顶的元素。
4.实现getMin操作:直接弹出最小栈的栈顶元素

4.3画图分析

1.实现push操作:
在这里插入图片描述

2.实现pop操作:

在这里插入图片描述

4.4代码实现

public class GetMinStack {
   Stack<Integer> stack= new Stack<>();
   Stack<Integer> Minstack= new Stack<>();
    //push
    public void push(int val) {
        //普通栈直接压栈
        stack.push(val);
        //最小栈压栈两种情况
        if(Minstack.empty()) {
            //1.最小栈为空栈,直接压栈。
            Minstack.push(val);
        }
        else {
            //2.最小栈不为空栈,则需要将压栈的元素与最小栈栈顶元素比较,当压栈元素<=最小栈栈顶元素则可以压栈
            if(val <= Minstack.peek()) {
                Minstack.push(val);
            }
        }
    }
    //pop
    public void pop() {
        int ret = stack.pop();
        if (ret == Minstack.peek()) {
            Minstack.pop();
        }
    }
    //peek
    public int peek() {
       return stack.peek();
    }
    //getMin
    public int getMin() {
       return Minstack.peek();
    }

    public static void main(String[] args) {
        GetMinStack getMinStack = new GetMinStack();
        getMinStack.push(-2);
        getMinStack.push(0);
        getMinStack.push(-3);
        System.out.println(getMinStack.getMin());
    }
}

结尾:希望大家可以给我点点关注,点点赞,并且在评论区发表你们的想法和意见,我会认真看每一条评论,你们的支持就是我的最大鼓励。🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹

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

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

相关文章

Spring Chache入门详解、配套小案例

简介&#xff1a;Spring Cache是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;只需要添加一个注解就能实现缓存功能。 Spring Cache提供了一层抽象&#xff0c;底层可以切换不同的缓存实现&#xff0c;如下&#xff1a; EHCacheCaffeineRedis (这篇帖子&#xff…

Xcode调试Qt 源码

在Mac下使用Xcode 开发Qt程序&#xff0c;由于程序断点或者崩溃后&#xff0c;Qt库的堆栈并不能够正确定位到源码的cpp文件&#xff0c;而是显示的是汇编代码&#xff0c;导致不直观的显示。 加载的其他三方库都是同理。 所以找了攻略和研究后&#xff0c;写的这篇文章。 一&a…

网络原理(1)——UDP协议

目录 一、应用层 举个例子&#xff1a;点外卖 约定数据格式简单粗暴的例子 客户端和服务器的交互&#xff1a; 序列化和返序列化 xml、json、protobuffer 1、xml 2、json 3、protobuffer 二、传输层 端口 端口号范围划分 认识知名的端口号 三、UDP协议 端口 U…

NCP1380BDR2G芯片中文资料规格书PDF数据手册引脚图图片参数功能价格

产品描述&#xff1a; NCP1380 是一款高性能器件&#xff0c;旨在为准谐振转换器供电。该控制器基于专属的谷锁闭系统&#xff0c;可以在功率负载变轻时进行切换并降低开关频率。这样将产生稳定的运行&#xff0c;即使在漏极-源极谷中总是触发的开关事件下也是如此。此系统可在…

蓝膜胶带(蓝膜)为动力电池电气绝缘主流应用方案之一 市场需求空间较广阔

蓝膜胶带&#xff08;蓝膜&#xff09;为动力电池电气绝缘主流应用方案之一 市场需求空间较广阔 动力电池蓝膜胶带是一种PET基材背上PSA压敏胶制成的单面胶带&#xff0c;因其以深蓝色居多&#xff0c;又被称为蓝膜。蓝膜为绝缘材料&#xff0c;可将电芯与电芯之间分隔开来&…

环保水离子水壁炉,现代时尚

环保水离子壁炉&#xff0c;现代而时尚&#xff0c;靠水运行&#xff0c;用电量很少。这绝对是最生态的壁炉。完全安全&#xff08;带冷火焰&#xff09;&#xff0c;其现代设计完美适应各种环境。凭借最低的碳足迹&#xff0c;它无疑是未来的混合壁炉。 什么是环保壁炉&#x…

JUC之CAS比较并交换

CAS 原子类引入 加入原子整型类的操作后&#xff0c;无锁化的操作 CAS 比较并交换 硬件级别的保证 源码分析 引出UnSafe类 UnSafe源码分析 unsafe中的do-while保证自旋 public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 this…

Linux:kubernetes(k8s)有状态的服务部署(14)

之前我都是对无状态进行的一个操作&#xff0c;我们想扩容就扩容&#xff0c;想缩容就缩容&#xff0c;根本不用去考虑他的一个网络环境&#xff0c;本地储存环境啥的一个状态 当我们做有状态的服务的操作&#xff0c;肯定要申请一个持久化的一个空间&#xff0c;以及网络&…

Linux环境(Ubuntu)上的防火墙工具使用方法

目录 概述 1 防火墙工具&#xff08;ufw&#xff09; 1.1 安装防火墙工具&#xff1a; 1.2 操作防火墙相关命令 2 ufw操作命令的范例 2.1 打开/关闭防火墙 2.1.1 打开防火墙 2.1.2 关闭防火墙 2.1.3 查询当前防火墙状态 2.1.4 允许选择的端口访问 2.1.5 允许选择固定…

自动写作软件哪个好?分享7款独家推荐

随着人工智能技术的不断发展&#xff0c;自动写作软件正逐渐成为现代写作的利器。这些AI写作工具能够帮助用户高效地生成文章、报告、新闻稿等内容&#xff0c;为写作工作带来了极大的便利。然而&#xff0c;市面上的自动写作软件琳琅满目&#xff0c;让人眼花缭乱。为了帮助读…

SpringCloud返回的是xml格式而非JSON数据

一、问题描述&#xff1a; 最近接触eureka&#xff0c;写了一个接口&#xff0c;使用RestController注解修饰了类&#xff0c;预期是返回json格式的数据&#xff0c;但是结果返回的是xml格式的数据。 二、问题分析&#xff1a; 原因是因为直接或间接引入了jackson-dataformat…

相机拍照与摄影学基础

1.相机拍照 相机可能形状和大小不同&#xff0c;但基本功能相同&#xff0c;包括快门速度、光圈和景深&#xff0c;这些是摄影的通用概念。即使是一次性相机也是基于这三个理念工作的。不同类型相机在这三个概念上的唯一区别是你可以控制这些功能的程度。这三个参数被称为相机…

mybatis+thymeleaf登录

目录 一.将页面显示在浏览器中 1.新建项目并导入页面 2.使用th标签 3.新建控制层 4.显示结果 二.将两个页面进行关联 1.提交表单 2.跳转页面 3.结果 三.登录账号名动态改变 1.获取登录表单数据 2.给页面传值 3.页面显示 4.结果 四.连接数据库 1.新建数据库 2.…

tcp/ip协议2实现的插图,数据结构8 (30 - 32章)

(201) 201 三十0 中断优先级补充 (202) 202 三十1 TCP的用户需求 函tcp_usrreq一 (203) 203 三十2 TCP的用户需求 函tcp_usrreq二 (204) 204 三十3 TCP的用户需求 函tcp_usrreq三 (205) 205 三十4 TCP的用户需求 函tcp_usrreq四 (206) 206 三十5 TCP的用户需求 函tcp_usrreq五 …

C语言 内存函数

目录 前言 一、memcpy()函数 二、memmove()函数 三、memset函数 四、memcmp()函数 总结 前言 在C语言中内存是我们用来存储数据的地址&#xff0c;今天我们来讲一下C语言中常用的内存函数。 一、memcpy()函数 memcpy()函数与我们之前讲的strcpy()函数类似&#xff0c;只…

[SAP ABAP] 创建事务码T-CODE

如何让用户通过输入事务码T-CODE跳转到Z437_TEST_2024程序输出界面&#xff1f; 1.输入事务码SE39&#xff0c;进入到维护事务的界面 2.输入需要创建的事务码名称(一般情况下用Y或者Z开头)&#xff0c;点击【创建】 这里我们创建一个名为ZTEST437的事务代码 3.在创建事务的窗口…

springboot爱看漫画小程序的设计与实现

摘 要 相比于以前的传统手工管理方式&#xff0c;智能化的管理方式可以大幅降低爱看漫画的运营人员成本&#xff0c;实现了爱看漫画的标准化、制度化、程序化的管理&#xff0c;有效地防止了爱看漫画的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能够及时、…

leetcode代码记录(子集

目录 1. 题目&#xff1a;2. 我的代码&#xff1a;小结&#xff1a; 1. 题目&#xff1a; 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的 子集 &#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 …

MySQL MHA故障切换

目录 一、案例分析 1.1、案例概述 1.2、案例前置知识点 1&#xff09;什么是 MHA 2&#xff09;MHA 的组成 3&#xff09;MHA 的优势 4&#xff09;MHA 现状 1.3、案例环境 1&#xff09;本案例环境 ​编辑 2&#xff09;案例需求 3&#xff09;案例实现思路…

解读如何打造超高商楼宇智慧公厕

智慧楼宇大厦智慧公厕是近年来兴起的一个创新方案&#xff0c;旨在为现代城市的楼宇建筑提供一种全新的管理与服务模式。这种智慧公厕的最大特点就是将智能化技术与传统楼宇公厕结合&#xff0c;通过各种高科技设备与系统&#xff0c;实现对公厕的全新管理与监控&#xff0c;为…