刷题计划 day10 栈与队列上【用栈实现队列】【用队列实现栈】【有效的括号】【删除字符串中的所有相邻重复项】

⚡刷题计划day10栈与队列继续,可以点个免费的赞哦~

往期可看专栏,关注不迷路,

您的支持是我的最大动力🌹~

目录

⚡刷题计划day10继续,可以点个免费的赞哦~

往期可看专栏,关注不迷路,

您的支持是我的最大动力🌹~

题目一:232. 用栈实现队列

题目二:225. 用队列实现栈

法一:两个队列

法二:一个队列

题目三:20. 有效的括号

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

法一:使用ArrayDeque作为堆栈(效率一般)

法二:将字符串直接作为栈(效率较高)

法三:双指针(效率无敌高)


简单来说,栈是先进后出(FILO,First In Last Out),队列是先进先出(FIFO,First In First Out)的数据结构。

栈的常用操作

压栈(Push):将元素添加到栈顶。
弹栈(Pop):移除并返回栈顶元素。
查看栈顶元素(Peek):返回栈顶元素但不移除它。
检查栈是否为空(IsEmpty):判断栈是否没有任何元素。
获取栈的大小(Size):返回栈中元素的数量。

队列常用操作

入队(Offer):将元素添加到队列尾部。
出队(Poll):移除并返回队列头部的元素。
查看队首元素(Peek/Element):返回队列头部的元素但不移除它。
检查队列是否为空(IsEmpty):判断队列是否没有任何元素。
获取队列的大小(Size):返回队列中元素的数量。

题目一:232. 用栈实现队列

  1. 用栈实现队列

(https://leetcode.cn/problems/implement-queue-using-stacks/description/)

主要思路:

使用栈来模拟队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈一个输入栈,一个输出栈,这里要注意输入栈和输出栈的关系。

可以结合如下动画理解,这样就将栈转换为了队列:

注意几个点:

  • 在push时,直接将数据放进输入栈就可

  • 在pop时,会复杂一些,我们需要先判断输出栈是否为空,不为空直接输出;为空则需要将输入栈中的数据全部导入到输出栈,再弹出数据即可

  • 关于队列判空,如果进栈和出栈都为空的话,说明模拟的队列为空了。

代码如下:

import java.util.Stack;
​
class MyQueue {
​
    Stack<Integer> stackIn; // 负责进栈的栈
    Stack<Integer> stackOut; // 负责出栈的栈
​
    public MyQueue() {
        stackIn = new Stack<>(); // 初始化进栈栈
        stackOut = new Stack<>(); // 初始化出栈栈
    }
​
    public void push(int x) {
        stackIn.push(x); // 将元素x推入stackIn
    }
    
    public int pop() {
        dumpstackIn(); // 将stackIn中的元素转移到stackOut中
        return stackOut.pop(); // 弹出stackOut的栈顶元素
    }
    
    public int peek() {
        dumpstackIn(); // 将stackIn中的元素转移到stackOut中
        return stackOut.peek(); // 返回stackOut的栈顶元素但不移除
    }
​
    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty(); // 如果两个栈都为空,则队列为空
    }
​
    //将功能相近的函数要抽象出来,就是将输入栈中的数据导入到输出栈
    private void dumpstackIn() {
        if (!stackOut.isEmpty()) return; // 如果stackOut不为空,则不需要转移
        while (!stackIn.isEmpty()) { // 当stackIn不为空时
            stackOut.push(stackIn.pop()); // 将stackIn的栈顶元素弹出并推入stackOut
        }
    }
}

题目二:225. 用队列实现栈

  1. 用队列实现栈

(https://leetcode.cn/problems/implement-stack-using-queues/description/)

这题开始也想着和上题一样,使用一个输入队列,一个输出队列,但是仔细想一下,行不通。

队列是先进先出的规则,把一个队列中的数据导入另一个队列中,数据的顺序并没有变,并没有变成先进后出的顺序。

所以用栈实现队列, 和用队列实现栈的思路还是不一样的,这取决于这两个数据结构的性质。

下面解法一先给出两个队列的实现

如下面动画所示,用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。

法一:两个队列

AC代码如下:

class MyStack {
​
    Queue<Integer> queue1; // 主队列,用来模拟栈
    Queue<Integer> queue2; // 辅助队列,用于临时存储元素
​
    /** 
     * 初始化数据结构。
     */
    public MyStack() {
        queue1 = new LinkedList<>(); // 初始化主队列
        queue2 = new LinkedList<>(); // 初始化辅助队列
    }
    
    /** 
     * 将元素 x 压入栈顶。
     */
    public void push(int x) {
        queue2.offer(x); // 先将元素 x 放入辅助队列
        while (!queue1.isEmpty()){ // 将主队列中的所有元素转移到辅助队列
            queue2.offer(queue1.poll());
        }
        Queue<Integer> queueTemp; // 临时变量用于交换队列
        queueTemp = queue1; // 交换队列,此时queue2成为主队列
        queue1 = queue2;
        queue2 = queueTemp;
    }
    
    /** 
     * 移除并返回栈顶元素。
     */
    public int pop() {
        return queue1.poll(); // 由于queue1模拟栈,所以直接移除并返回队首元素
    }
    
    /** 
     * 获取栈顶元素。
     */
    public int top() {
        return queue1.peek(); // 返回queue1的队首元素,即栈顶元素
    }
    
    /** 
     * 判断栈是否为空。
     */
    public boolean empty() {
        return queue1.isEmpty(); // 如果主队列为空,则栈为空
    }
}

法二:一个队列

一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。

AC代码

class MyStack {
    Queue<Integer> queue;
​
    public MyStack() {
        queue = new LinkedList<>();
    }
​
    public void push(int x) {
        queue.offer(x);
        int size = queue.size();
        while (size-->1)//将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部
            queue.offer(queue.poll());
    }
​
    public int pop() {
       return queue.poll();
    }
​
    public int top() {
        return queue.peek();
    }
​
    public boolean empty() {
        return queue.isEmpty();
    }
}

题目三:20. 有效的括号

  1. 有效的括号

(https://leetcode.cn/problems/valid-parentheses/description/)

由于栈结构的特殊性,非常适合做对称匹配类的题目。

分析:

第一种情况,字符串里左(右)方向的括号多余了 ,所以不匹配。

已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false

第二种情况,括号没有多余,但是 括号的类型没有匹配上。

遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false

第三种情况,字符串里右方向的括号多余了,所以不匹配。

遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false

还有一些技巧,在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了!

根据以上分析三种情况实现,AC代码如下:

class Solution {
    public boolean isValid(String s) {
       if(s.length()%2 != 0){
          return false;
      }
       char[] c = s.toCharArray();
      Deque<Character> deque = new LinkedList<>();
      for (int i=0;i<s.length();i++){
         if(c[i] == '('){
            deque.push(')');
         }else if (c[i] == '{'){
            deque.push('}');
         }else if (c[i] == '['){
            deque.push(']');
         }else if(deque.isEmpty() || deque.peek()!=c[i]){
            return false;
         }else{
            deque.pop();
         }
      }
      return deque.isEmpty();
    }
}

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

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

(https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/description/)

本题要删除相邻相同元素,相对于[20. 有效的括号]来说其实也是匹配问题,[20. 有效的括号]是匹配左右括号,本题是匹配相邻元素,最后都是做消除的操作。

本题也是用栈来解决的经典题目。

法一:使用ArrayDeque作为堆栈(效率一般)

大致思路:

开始先将字符入栈,然后下一字符入栈前判断是否与已入栈字符相等。

若相等,则直接将栈中元素弹出,

若栈为空或不相等,则入栈,

将字符串遍历结束后,将栈中字符导出为字符串格式,因为从栈里弹出的元素是倒序的,所以再对字符串进行反转一下,就得到了最终的结果。

动画如图:

AC代码及注释:

class Solution {
    public String removeDuplicates(String s) {
        //1.ArrayDeque会比LinkedList在除了删除元素这一点外会快一点
        //2.在Java中,ArrayDeque 是双端队列的实现,它提供了队列和栈的功能。尽管它是一个队列,但它同时支持在两端进行操作,所以它也可以用来模拟栈的行为,直接调用对应方法即可。
        
      ArrayDeque<Character> queue = new ArrayDeque<>();
      char[] c = s.toCharArray();
      for(int i=0;i<s.length();i++){
         if(queue.isEmpty() || c[i] != queue.peek()){
            queue.push(c[i]);
         }else {
            queue.pop();
         }
      }
      String str = "";
      //注意这里挺妙,queue.pop() 作为第一个加数,这样我们就不需要再翻转字符串了。
      while (!queue.isEmpty()){
         str = queue.pop() +str;
      }
      return str;
​
    }
}

法二:将字符串直接作为栈(效率较高)

拿字符串直接作为栈,省去了栈还要转为字符串的操作,效率较高。

AC代码及注释:

class Solution {
    public String removeDuplicates(String s) {
        StringBuilder sb = new StringBuilder();
        for (char c : s.toCharArray()) {
            // 如果StringBuilder不为空,并且最后一个字符与当前字符相同
            if (sb.length() != 0 && sb.charAt(sb.length() - 1) == c) {
                // 删除StringBuilder中的最后一个字符
                sb.deleteCharAt(sb.length() - 1);
            } else {
                // 否则,将当前字符添加到StringBuilder中
                sb.append(c);
            }
        }
        return sb.toString();
    }
}

法三:双指针(效率无敌高)

AC代码及注释:

class Solution {
   public String removeDuplicates(String s) {
      char[] ch = s.toCharArray();
      int fast = 0;
      int slow = 0;
      while(fast < s.length()){
         // 直接用fast指针覆盖slow指针的值
         ch[slow] = ch[fast];
         // 遇到前后相同值的,就跳过,即slow指针后退一步,下次循环就可以直接被覆盖掉了
         if(slow > 0 && ch[slow] == ch[slow - 1]){
            slow--;
         }else{
            slow++;
         }
         fast++;
      }
      return new String(ch,0,slow);
   }
}

有所帮助可以点个免费的赞赞哦~🌹

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

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

相关文章

Vue引入js脚本问题记录(附解决办法)

目录 一、需求 二、import引入问题记录 三、解决方式 一、需求 我想在我的Vue项目中引入jquery.js和bootstrap.js这种脚本文件&#xff0c;但发现不能单纯的import引入&#xff0c;问题如下。 二、import引入问题记录 我直接这么引入&#xff0c;发现控制台报错TypeError: …

使用kaggle命令下载数据集和模型

点击用户头像&#xff0c;点击Settings&#xff1a; 找到API&#xff0c;点击create new token&#xff0c;将自动下载kaggle.json&#xff1a; 在用户目录下创建.kaggle文件夹&#xff0c;并将下载的kaggle.json文件移动到该文件夹&#xff1a; cd ~ mv Downloads/kaggle.j…

postman控制变量和常用方法

1、添加环境&#xff1a; 2、环境添加变量&#xff1a; 3、配置不同的环境&#xff1a;local、dev、sit、uat、pro 4、 接口调用 5、清除cookie方法&#xff1a; 6、下载文件方法&#xff1a;

数据结构升华部分:排序与字符串匹配算法应用

数据结构入门学习&#xff08;全是干货&#xff09;——综合应用 习题选讲 - 排序与字符串匹配算法 习题选讲 - Insert or Merge 习题-IOM.1 插入排序的判断 题意理解 如何区分简单插入和非递归的归并排序 插入排序&#xff1a;前面有序&#xff0c;后面没有变化。归并排…

react hooks--useCallback

概述 useCallback缓存的是一个函数&#xff0c;主要用于性能优化!!! 基本用法 如何进行性能的优化呢&#xff1f; useCallback会返回一个函数的 memoized&#xff08;记忆的&#xff09; 值&#xff1b;在依赖不变的情况下&#xff0c;多次定义的时候&#xff0c;返回的值是…

【计算机组成原理】实验一:运算器输入锁存器数据写实验

目录 实验要求 实验目的 主要集成电路芯片及其逻辑功能 实验原理 实验内容及步骤 实验内容 思考题 实验要求 利用CP226实验箱上的K16&#xff5e;K23二进制拨动开关作为DBUS数据输入端&#xff0c;其它开关作为控制信号的输入端&#xff0c;将通过K16&#xff5e;K23设定…

Linux:终端(terminal)与终端管理器(agetty)

终端的设备文件 打开/dev目录可以发现其中有许多字符设备文件&#xff0c;例如对于我的RedHat操作系统&#xff0c;拥有tty0到tty59&#xff0c;它们是操作系统提供的终端设备。对于tty1-tty12使用ctrlaltF*可以进行快捷切换&#xff0c;下面的命令可以进行通用切换。 sudo ch…

【Linux】项目自动化构建工具-make/Makefile 详解

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…

Studying-图论包含的算法总结

目录 1.DFS&#xff08;深度优先搜索&#xff09; 代码框架&#xff1a; 2. BFS&#xff08;广度优先搜索&#xff09; 代码框架&#xff1a; 3. 并查集 4.最小生成树之Prim 5.最小生成树之Kruskal 6.拓扑排序 7. 最短路径之-dijkstra&#xff08;朴素版&#xff…

[附源码]在线音乐系统+SpringBoot+Vue前后端分离

今天带来一款优秀的项目&#xff1a;在线音乐系统源码 。 系统采用的流行的前后端分离结构&#xff0c;内含功能包括 "管理后台"&#xff0c;“用户端”&#xff0c;“评论系统”&#xff0c;“歌手&#xff0c;歌曲管理”&#xff0c;“用户系统”,"统计"…

c++继承详解

从这篇文章开始&#xff0c;我们正式进入c进阶篇章 继承的概念及定义 概念 继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段&#xff0c;它允许我们在保持原有 类特性的基础上进⾏扩展 通俗来讲就是&#xff1a;父亲的遗产传给自己的子女&#xff0c;…

Autosar学习----AUTOSAR_SWS_BSWGeneral(七)

&#x1f4a5;&#x1f4a5;&#x1f50d; &#x1f50d; 欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f421;优势&#xff1a;❤️博客内容尽量做到通俗易懂&#xff0c;逻辑清晰。 ⛳️座右铭&#xff1a;恒心&#xff0c;耐心&#xff0c;静心。 ⛳️ 欢迎一起…

力扣958:判断二叉树是否为完全二叉树

给你一棵二叉树的根节点 root &#xff0c;请你判断这棵树是否是一棵 完全二叉树 。 在一棵 完全二叉树 中&#xff0c;除了最后一层外&#xff0c;所有层都被完全填满&#xff0c;并且最后一层中的所有节点都尽可能靠左。最后一层&#xff08;第 h 层&#xff09;中可以包含 …

828华为云征文|Flexus云服务器X实例实践:安装SimpleMindMap思维导图工具

828华为云征文&#xff5c;Flexus云服务器X实例实践&#xff1a;安装Ward服务器监控工具 引言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 主要使用场景 二、购买Flexus云服务器X实例2.1 购买规格参考2.2 查看Flexus云服务器X实例状态 三、远程连接Flexus云服务…

AIGAME的核心技术竞争力与未来生态规划

AIGAME凭借其领先的区块链和人工智能技术&#xff0c;打造了全球首个融合链游、DeFi和加密聊天的Web3娱乐平台。平台的核心技术创新和多元化生态规划&#xff0c;将推动全球虚拟资产管理和娱乐行业的变革。 AIGAME的核心技术竞争力源于其对区块链和人工智能&#xff08;AI&…

衡石分析平台系统管理手册-功能配置之SMTP 服务

SMTP 服务​ SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议。它是一组用于从源地址到目的地址传输邮件的规范&#xff0c;通过它来控制邮件的中转方式。 HENGSHI 用户需要开启 SMTP 服务并进行配置&#xff0c;才能收到系统发送邮件。 SMTP 服务需要用户配置服务器…

Linux(含麒麟操作系统)如何实现多显示器屏幕采集录制

技术背景 在操作系统领域&#xff0c;很多核心技术掌握在国外企业手中。如果过度依赖国外技术&#xff0c;在国际形势变化、贸易摩擦等情况下&#xff0c;可能面临技术封锁和断供风险。开发国产操作系统可以降低这种风险&#xff0c;确保国家关键信息基础设施的稳定运行。在一…

Java文件上传同时传入JSON参数

前言 此篇文章用于解决一个接口内同时完成文件的上传及JSON参数的传入(生产环境已验证); 1.准备接口 import cn.cdjs.vo.UserVO; import cn.hutool.json.JSONUtil; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFi…

虚拟社交的新时代:探索Facebook的元宇宙愿景

随着技术的不断进步&#xff0c;社交媒体的形态也在悄然变化。Facebook&#xff08;现名Meta&#xff09;正站在这一变革的前沿&#xff0c;积极探索元宇宙的愿景。元宇宙不仅是虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;的结合&#xff0c;更是…

Qt_对话框QDialog的介绍

目录 1、新建项目对话框 2、非模态对话框 3、模态对话框 4、自定义对话框 5、Qt内置对话框 5.1 消息对话框QMessageBox 5.2 颜色对话框QColorDialog 5.3 文件对话框QFileDialog 5.4 字体对话框QFontDialog 5.5 输入对话框QInputDialog 结语 前言: 在Qt中&…