Leetcoder Day10|栈与队列part02(栈的应用)

语言:Java/C++ 

目录

20. 有效的括号 

1047. 删除字符串中的所有相邻重复项 

150. 逆波兰表达式求值

今日总结


20. 有效的括号 

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 注意空字符串可被认为是有效字符串。

由于栈的特殊性(FILO),很适合解决对称匹配类问题。括号匹配就是使用栈解决的经典问题。

因为我们的阅读习惯都是从左至右的,所以往往先出现的都是左括号,因此先设置一个匹配栈,用于存放应该与已经出现的左括号所匹配的右括号,并且,先出现的左括号对应的右括号类型往往是后出现的,这个情况非常适合栈的特点,先进后出。如输入的字符串为"{[()]}"第一个出现的是"{"因此我们在栈中存放一个"}",并且它是这个字符串的最后一个字符。因为已经对应左括号将应该出现的右括号都放入栈中了,当遍历到第一个右括号字符时,开始进行出栈操作

遇到匹配问题,首先要进行分类,找出可能出现的情况,对于本题会出现以下三种情况:

  1. 字符串里左方向的括号多余:字符串结束栈还不为空。
  2. 字符串里右方向的括号多余:栈为空时,字符串还没结束。
  3. 字符串里括号没有多余,但是不匹配:遍历字符串时,栈顶右括号与当前字符串所指的字符不匹配。
class Solution {
    public boolean isValid(String s) {
         Stack<Character> stack=new Stack<>(); 
         if(s.length() % 2==1) return false;
         for(int i=0; i<s.length();i++){
             char ch=s.charAt(i);
             //将与左括号匹配的右括号压入栈中
             if (ch=='{') stack.push('}');
             else if(ch=='(') stack.push(')');
             else if(ch=='[') stack.push(']');
             //若栈提前为空或当前字符不等于弹出来的右括号,则返回false
             else if (stack.isEmpty() || stack.peek()!= ch) return false;
             else stack.pop();
         }   
         //若字符串为空栈不为空
         return stack.isEmpty();
    }
}

⚠️ 在进行情况判断的时候,一定要记住是stack.peek()!= ch,而不是stack.pop()!=ch,否则会导致java.util.EmptyStackException 异常。因此已经进行了一次pop操作了。


1047. 删除字符串中的所有相邻重复项 

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

  • 输入:"abbaca"
  • 输出:"ca"
  • 解释:例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

提示:

  • 1 <= S.length <= 20000
  • S 仅由小写英文字母组成。

因为本题涉及两个相邻且相同,转换思路就是,如果字符串里存在对称的结构,我们就会进行删除,实际上跟上一题有效括号匹配的题思路是一样的。只不过在括号里我们要判断的是不匹配的情况,而这里我们要删除匹配的情况因此可以将字符串遍历,先判断再入栈,如果当前字符与栈顶元素相同,则把栈顶元素弹出,如果不等,则放入栈中。随后将栈中剩余的元素依次弹出再把字符串进行翻转返回即可。如果是Java,使用StringBuilder类的reverse()方法来翻转字符串。

⚠️使用栈的用时和内存都较高,因此使用ArrayDeque效率会更高,删除会更快而且节省了翻转操作。

//使用栈
class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> stack = new Stack<>();
        for(int i=0;i<s.length();i++){
             char ch=s.charAt(i);
             if(stack.isEmpty()||stack.peek()!=ch) stack.push(ch);
             else stack.pop();
        }
        s = "";
        while(!stack.isEmpty()){
            s+=stack.pop(); 
        }
        StringBuilder sb = new StringBuilder();
        for(int i=s.length()-1;i>=0;i--){
            sb.append(s.charAt(i));
        }
        return sb.toString();
    }
}

//使用deque

class Solution {
    public String removeDuplicates(String s) {
        ArrayDeque<Character> deque = new ArrayDeque<>();
        for(int i=0;i<s.length();i++){
             char ch=s.charAt(i);
             if(deque.isEmpty()||deque.peek()!=ch) deque.push(ch);
             else deque.pop();
        }
        s = "";
        while(!deque.isEmpty()){
            s+=deque.pollLast();
        }
        return s;
        
    }
}

优化的方法还可以拿字符串直接作为栈,省去了栈还要转为字符串的操作。这样的话设置一个指针top,指向字符串末尾元素,即栈顶。

class Solution {
    public String removeDuplicates(String s) {
        StringBuffer str=new StringBuffer();
        int top=-1; //设置一个指针指向栈顶,即字符串尾部
        for(int i=0;i<s.length();i++){
            char ch=s.charAt(i);
            if(top>=0 && str.charAt(top)==ch){
                str.deleteCharAt(top);
                top--;
            }
            else{
                // 将当前元素接入字符串,top指向最后一个元素
                str.append(ch);
                top++;
            }
        }
        return str.toString();
        
    }
}

150. 逆波兰表达式求值

根据逆波兰表示法,求表达式的值。

逆波兰表达式:是一种后缀表达式,所谓后缀就是指运算符写在后面。

有效的运算符包括 + ,  - ,  * ,  / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明:

整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:

  • 输入: ["2", "1", "+", "3", " * "]
  • 输出: 9
  • 解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

示例2:
  • 输入:tokens = ["4","13","5","/","+"]
    输出:6
    解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

逆波兰表达式主要有以下两个优点

  • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
  • 适合用栈操作运算:遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中。

根据逆波兰的第二个优点其实本题的做法就已经呼之欲出了,数据结构中,后缀表达式往往可以用后序二叉树展现出来。本题思路可以简化为,遇到一个符号则把符号前面的拿出来进行符号对应的操作再压入栈中,很像上一题相邻重复项的思路,只不过这里的重复项定义为数字。

⚠️本题有几个需要注意的语法事项:

  1. 这里的tokens定义的是数组类型,因此不能用length()方法来提取长度而是使用length
  2. 在进行减法操作时,不能简单的使用deque.pop() - deque.pop(),不然如下图会变成’3-4‘,因为这个是栈,遵守先进后出原则,减数应该在被减数前被弹出来的,所以要用- deque.pop()+deque.pop()才可以表达‘4-3’的结果。

  3. 同理,除法操作也应该注意。
  4. 将数字存入栈时,应该注意转换为整型
class Solution {
    public int evalRPN(String[] tokens) {
        ArrayDeque<Integer> deque=new ArrayDeque<>();
        for (int i = 0; i < tokens.length; i++) {
            String ch = tokens[i];
            if(ch.equals("+")) deque.push(deque.pop() + deque.pop());
            //因为是栈,被减数是在减数后被弹出的
            else if(ch.equals("-")) deque.push(-deque.pop() + deque.pop());
            else if(ch.equals("*")) deque.push(deque.pop() * deque.pop());
            else if(ch.equals("/")) {
                int temp1 = deque.pop();//因为是栈,被除数是在除数后被弹出的
                int temp2 = deque.pop();
                deque.push(temp2 / temp1);
            }
            else deque.push(Integer.valueOf(ch));
        }
        return deque.pop();
    }
}

今日总结

今天主要进行了对栈常规问题的练习,遇到对称消除,对称匹配时,首选栈进行操作,且操作时要注意压入,弹出的顺序,不可搞混。且递归就是用栈来实现

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WEB接口测试之Jmeter接口测试自动化 (三)(数据驱动测试)

接口测试与数据驱动 1简介 数据驱动测试&#xff0c;即是分离测试逻辑与测试数据&#xff0c;通过如excel表格的形式来保存测试数据&#xff0c;用测试脚本读取并执行测试的过程。 2 数据驱动与jmeter接口测试 我们已经简单介绍了接口测试参数录入及测试执行的过程&#xff0…

Unity3D Pico VR 手势识别物体交互 适配 MRTK3

当前Pico已经支持手势识别了&#xff0c;但是提供的PICO Unity Integration SDK 中是没有手势和物体交互的功能&#xff0c;Unity XR Interaction Toolkit提供的手势识别物体交互对 Quest适配的挺好的&#xff0c;Pico 当前只能用指尖点触还不能对物体进行抓握以及手势控制射线…

数据结构一:算法效率分析(时间复杂度和空间复杂度)-重点

在学习具体的数据结构和算法之前&#xff0c;每一位初学者都要掌握一个技能&#xff0c;即善于运用时间复杂度和空间复杂度来衡量一个算法的运行效率。所谓算法&#xff0c;即解决问题的方法。同一个问题&#xff0c;使用不同的算法&#xff0c;虽然得到的结果相同&#xff0c;…

开发实践8_project

要求&#xff1a; 使用Restful对Chaos模型作基本操作。 结果&#xff1a; post 3 组数据后&#xff0c;get 查询如下&#xff1a; put修改后get&#xff1a; delete pk3之后get&#xff1a; 代码&#xff1a; python manage.py startapp pro8_app 注册 总路由 // path(pr…

免费200万Tokens 用科大讯飞API调用星火大模型服务

简介 自ChatGPT火了之后&#xff0c;国内的大模型发展如雨后春笋。其中的佼佼者之一就是科大讯飞研发的星火大模型,现在大模型已经更新到V3 版本&#xff0c;而且对开发者也是相当友好&#xff0c;注册就送200万tokens,讯飞1tokens 约等于 1.5 个中文汉字 或者 0.8 个英文单词…

JVM 如何判断一个对象可以被回收

Hi&#xff0c; 我是 浮生。 今天分享一道一线互联网公司必问的面试题。 ”JVM 如何判断一个对象可以被回收“ 关于这个问题&#xff0c;来看看高手的回答。 一、问题解析 在 JVM 里面&#xff0c;要判断一个对象是否可以被回收&#xff0c;最重要的是判断这个对象是否还在被…

中仕教育:省考怎么查每个岗位报考人数?一篇文章带你搞定!

参加省考避开热门岗位能够一定程度上提高上岸几率&#xff0c;怎么看岗位报考人数? 1. 官方公告&#xff1a;每年省考发布招录公告时&#xff0c;会公布各个岗位的招录人数&#xff0c;可以关注招录信息。 2. 查询报名数据&#xff1a;在报名结束后&#xff0c;省考招录机关…

debian12.4配置

文章目录 debian12.4配置概述笔记将非root用户添加到sudo组更换国内源配置ssh的客户端访问END debian12.4配置 概述 在虚拟机中装了一个debian12.4, 想配置ssh客户端连接, 出了问题. 配置乱了, 还好长了个心眼, 做了快照. 发现2个问题: debian12.4默认安装完, 有ssh, 先检查…

Python自动化测试【selenium面试题】

一、selenium中如何判断元素是否存在&#xff1f; expected_conditions模块提供了16种判断方法&#xff0c;以下方法是判断元素存在DOM中&#xff1a; presence_of_element_located """ An expectation for checking that an element is present on the DOM of…

【Linux】第三十一站:管道的一些应用

文章目录 一、我们之前的|(竖划线)管道二、自定义shell三、使用管道实现一个简易的进程池1.详解2.代码3.一个小bug4.最终代码 一、我们之前的|(竖划线)管道 cat test.txt | head -10 | tail -5如上代码所示&#xff0c;是我们之前所用的管道 我们拿下面这个举个例子 当我们用…

【SpringBoot】—— 如何创建SpringBoot工程

SpringBoot简化了Spring应用的初始搭建和开发过程。 工程创建 新建模块 出现java: 错误: 无效的源发行版&#xff1a;18这样的错误&#xff0c; 修改pom.xml文件 出现以下信息&#xff0c;即运行成功 修改默认端口 创建application.yml文件 内容&#xff1a; server:port:…

【没学过编程语言,想要做一款游戏应该怎么做?】

*** 【没学过编程语言&#xff0c;想要做一款游戏应该怎么做&#xff1f;】 想让你的创意成为像《堡垒之夜》《原神》这样引爆式的热门游戏吗&#xff1f; 想制作一个能与《我的世界》《模拟城市》一决高下的畅销游戏吗&#xff1f; 即使你手头并没有复杂的代码能力&#xf…

知识图谱KG+大模型LLM

LLM-based KG KnowLM OpenSPGKG-based RAG 基本原理 从query出发的语义解析 pre-LLM方法 思想&#xff1a;直接将问题解析为对应的逻辑表达式&#xff0c;然后到知识图谱中查询。 方法&#xff1a;通常包含逻辑表达式、语义解析算法、语义解析模型训练三部分。一般步骤是将问句…

【51单片机Keil+Proteus8.9+ADC0804】ADC实验 模拟转数字实验

一、实验名称 ADC实验 模拟转数字实验 二、设计思路 电路设计 1.选用AT89C51单片机作为电路核心单元&#xff0c;外接8位单通道AD转换器ADC0804芯片和LM016L显示器以及滑动变阻器等其它常用元器件构成电路。 2.将ADC0804芯片的控制引脚RD,WR,INTR接到AT89C51芯片对应引脚&…

管理信息系统知识点复习

目录 一、名词解释题1.企业资源规划(ERP)2.面向对象方法&#xff1a;3.电子健康&#xff1a;4.供应链5.数据挖掘6.“自上而下”的开发策略&#xff1a;7.业务流程重组8.面向对象&#xff1a;9.决策支持系统10.聚类11.集成开发环境&#xff1a;12.供应商协同13.数据仓库14.深度学…

pytorch集智-6手写数字加法机-迁移学习

1 概述 迁移学习概念&#xff1a;将已经训练好的识别某些信息的网络拿去经过训练识别另外不同类别的信息 优越性&#xff1a;提高了训练模型利用率&#xff0c;解决了数据缺失的问题&#xff08;对于新的预测场景&#xff0c;不需要大量的数据&#xff0c;只需要少量数据即可…

STM32407用汇顶的GT911触摸芯片调试实盘

这个配置很关键 代码 #include "stm32f4xx.h" #include "GT9147.h" #include "Touch.h" #include "C_Touch_I2C.h" #include "usart.h" #include "delay.h" #include "LCD.h" #incl…

Java String基础学习

目录 1、String的构造方法 2、String内存模型 3、字符串的比较 4、字符串的练习 1、用户登录系统 2、遍历字符串 3、统计字符次数 4、拼接字符串 5、字符串的反转 6、金额转换 7、手机号屏蔽 * 8、身份证信息查看 9、敏感词替换 5、StringBuilder 1、概念及练习…

新手也能看懂的【前端自动化测试入门】!

前言 最近在网上搜索前端自动化测试相关的文档&#xff0c;但是发现网上的文章都是偏使用&#xff0c;没有把一些基础概念说清楚&#xff0c;导致后续一口气遇到一些karma、Jasmine、jest、Mocha、Chai、BDD等词汇的时候很容易一头雾水&#xff0c;这次一方面整理一下收获的知…

YOLOv8改进 | 进阶实战篇 | 利用YOLOv8进行视频划定区域目标统计计数

一、本文介绍 Hello,各位读者,最近会给大家发一些进阶实战的讲解,如何利用YOLOv8现有的一些功能进行一些实战, 让我们不仅会改进YOLOv8,也能够利用YOLOv8去做一些简单的小工作,后面我也会将这些功能利用PyQt或者是pyside2做一些小的界面给大家使用。 在开始之前给大家推…