算法日记day 12(栈实现队列|队列实现栈|有效的括号)

news2024/9/20 18:39:14

队列是先进先出的,就像排队一样,谁在前谁先获得服务

栈是一种先进后出的数据结构

一、用栈实现队列

题目:

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 你 只能 使用标准的栈操作 —— 也就是只有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

示例 1:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

思路:

如何用栈实现先进先出的操作呢?

由于栈底元素是第一个入栈的,为了让他在栈结构中变成第一个出栈的元素,可以设置两种栈,一种负责入栈,一种负责出栈, 如果要实现先进先出,可以让元素先进入栈(push),当需要返回首元素时(peek)将入栈中的元素传进出栈中,这样出栈中第一个出去的元素就是入栈中的栈底元素了

代码:

class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    public MyQueue() {
        stackIn = new Stack<>();
        stackOut = new Stack<>();
    }

    public void push(int x) {
        stackIn.push(x);
    }

    public int pop() {
        dumpstackIn();
        return stackOut.pop();
    }

    public int peek() {
        dumpstackIn();
        return stackOut.peek();
    }

    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }

    private void dumpstackIn() {
        if (!stackOut.isEmpty())
            return;
        while (!stackIn.isEmpty()) {
            stackOut.push(stackIn.pop());
        }
    }
}

解释每个方法的功能:

  1. 构造函数 MyQueue()

    • 初始化两个栈 stackIn 和 stackOutstackIn 用于入队操作,stackOut 用于出队操作。
  2. push(int x) 方法

    • 将元素 x 压入 stackIn 中,实现入队操作。
  3. pop() 方法

    • 调用 dumpstackIn() 方法确保 stackOut 中有元素(如果为空的话),然后弹出 stackOut 的栈顶元素,即实现出队操作。
  4. peek() 方法

    • 同样调用 dumpstackIn() 方法确保 stackOut 中有元素,然后返回 stackOut 的栈顶元素,即查看队首元素但不移除。
  5. empty() 方法

    • 判断两个栈是否都为空,如果都为空则队列为空。
  6. 辅助方法 dumpstackIn()

    • 当需要从 stackOut 取元素时,确保 stackOut 中有元素,如果 stackOut 为空,则将 stackIn 中的所有元素逐个弹出并压入 stackOut,以实现从队列头部取元素。

 以示例进行代码分析:

输入:

["MyQueue", "push", "push", "peek", "pop", "empty"]

[[], [1], [2], [], [], []]

输出:

[null, null, null, 1, 1, false]

 初始化队列,创建一个空队列

MyQueue myQueue = new MyQueue();

 push操作,队列变为[1]

myQueue.push(2);

 再次push操作,队列变为[1,2]

myQueue.push(1);

peek操作,返回队首元素,即为1

myQueue.peek();

pop移除队首元素并返回,此时队列变为:[2]

myQueue.pop();

empty判断队列是否为空,此时队列为:[2],不为空,因此返回false

myQueue.empty();

二、用队列实现栈

题目:

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

思路:

队列实现栈的方法有很多,可以像栈实现队列一样用两个队列,一个存储一个输出,但是这种方法比较麻烦一些,用一个队列实现一个栈会更加简单,如何实现呢,由于队列是先进先出的,栈顶元素的返回即为队列中刚进队的队头元素, 如何用一个队列实现返回队头元素呢,只需要将队列中其他的元素全部出队,然后再次进队,留下的唯一元素就是所需的对头元素了,即为栈顶的元素

代码:

class MyStack {

    Queue<Integer> queue;

    // 辅助方法:重新排列队列中的元素,将队列头部的元素移到尾部
    public void rePosition() {
        int size = queue.size();
        size--; // 将队列最后一个元素移到队首之前的所有元素挪动到末尾
        while (size-- > 0) {
            queue.add(queue.poll()); // 将队列的头部元素移到尾部
        }
    }

    // 构造函数:初始化一个空队列
    public MyStack() {
        queue = new LinkedList<>();
    }

    // 入栈操作:将元素加入队列尾部
    public void push(int x) {
        queue.add(x);
    }

    // 出栈操作:调用 rePosition() 将队列头部元素移到尾部,然后移除队列的头部元素并返回
    public int pop() {
        rePosition();
        return queue.poll(); // 弹出队列的头部元素
    }

    // 获取栈顶元素:调用 rePosition() 将队列头部元素移到尾部,然后获取队列的头部元素并返回,再将该元素重新加入队列尾部
    public int top() {
        rePosition();
        int result = queue.poll(); // 弹出队列的头部元素
        queue.add(result); // 将该元素重新加入队列尾部,模拟栈的操作
        return result; // 返回栈顶元素
    }

    // 判断栈是否为空:判断队列是否为空
    public boolean empty() {
        return queue.isEmpty();
    }
}

 解释每个方法的功能:

  1. 构造函数 MyStack()

    • 初始化一个空的队列 queue,用来存储栈的元素。
  2. rePosition() 方法

    • 重新排列队列中的元素,将队列的头部元素移到尾部,以实现栈的后进先出特性。它通过将队列中的前面的元素依次移动到队列尾部来完成。
  3. push(int x) 方法

    • 将元素 x 加入队列的尾部,实现栈的入栈操作。
  4. pop() 方法

    • 调用 rePosition() 方法将队列的头部元素移到尾部,然后移除队列的头部元素并返回,模拟栈的出栈操作。
  5. top() 方法

    • 调用 rePosition() 方法将队列的头部元素移到尾部,然后获取队列的头部元素并返回,再将该元素重新加入队列的尾部。这样可以返回栈顶元素但不移除它,模拟栈的获取栈顶元素操作。
  6. empty() 方法

    • 判断队列是否为空,从而判断栈是否为空。

以示例进行代码分析:

输入:

["MyStack", "push", "push", "top", "pop", "empty"]

[[], [1], [2], [], [], []]

输出:

[null, null, null, 2, 2, false]

 创建栈对象,返回值为空

MyStack myStack = new MyStack();

将元素1入栈,此时栈中元素为[1]

myStack.push(1);

将元素2入栈,此时栈中元素为[1,2]

myStack.push(2);

调用top方法,返回栈顶元素,返回值为2

myStack.top();

 调用pop方法移除并返回栈顶元素,移除返回的元素为2,此时栈中元素为[1]

myStack.pop();

调用empty方法判断,此时栈中不为空,因此返回false

myStack.empty();

三、有效的括号

题目:

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

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

思路:

可以使用栈结构存储对应左括号的右括号类型,当检索到右括号时与栈顶匹配,分为三种情况

第一种:遍历完所有元素后,栈中仍有元素,说明有相应的左括号没有右括号来匹配(左括号数量多于右括号)

第二种:遍历过程中,栈中没有要匹配的字符

第三种,遍历过程中,发现栈已经为空(右括号多于左括号)

当字符串全部遍历完且栈为空,说明左右括号均匹配

代码:

public boolean isValid(String s) {
    Stack<Character> stack = new Stack<>();
    char c;
    for (int i = 0; i < s.length(); i++) {
        //使用一个 for 循环遍历字符串 s 的每个字符,从头到尾依次处理每个字符。
        c = s.charAt(i);
        //如果当前字符 c 是左括号 '(', '[', '{',则将对应的右括号 ')', ']', '}' 推入栈中
        //这样,栈中存放的就是遇到的左括号所对应的期望右括号。
        if (c == '(')
            stack.push(')');
        else if (c == '[')
            stack.push(']');
        else if (c == '{')
            stack.push('}');
        //如果当前字符 c 是右括号 ')', ']', '}',则检查栈顶的字符是否与 c 匹配
        //如果栈为空(即没有左括号与之对应),或者栈顶字符与 c 不匹配,说明当前的括号序列不合法,直接返回 false。
        //如果栈顶字符与 c 匹配,则将栈顶元素弹出,表示找到了一个匹配的括号对。
        else if (stack.isEmpty() || stack.peek() != c) {
            return false;
        } else {
            stack.pop();
        }
    }
    //最后,检查栈是否为空。
    //如果栈为空,说明所有的左括号都找到了对应的右括号,返回 true,表示输入的字符串 s 是有效的括号序列;否则返回 false,表示存在未匹配的括号
    return stack.isEmpty();
}

今天的学习就到这里了

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

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

相关文章

GuLi商城-商品服务-API-品牌管理-品牌分类关联与级联更新

先配置mybatis分页&#xff1a; 品牌管理增加模糊查询&#xff1a; 品牌管理关联分类&#xff1a; 一个品牌可以有多个分类 一个分类也可以有多个品牌 多对多的关系&#xff0c;用中间表 涉及的类&#xff1a; 方法都比较简单&#xff0c;就不贴代码了

可解释医学视觉问答的反事实因果干预| 文献速递-基于深度学习的多模态数据分析与生存分析

Title 题目 Counterfactual Causal-Effect Intervention for Interpretable Medical Visual Question Answering 可解释医学视觉问答的反事实因果干预 01 文献速递介绍 深度学习的进步在计算机视觉、自然语言处理和信息检索领域成功地取得了最先进的&#xff08;SOTA&…

SpringBoot连接PostgreSQL+MybatisPlus入门案例

项目结构 一、Java代码 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://mave…

基于秒杀系统的企业开发设计思考

一、需求分析 需求描述为实现某商品秒杀活动&#xff0c;结果为商品库存为0&#xff0c;订单数量和商品原有库存数量相等&#xff0c;即保障系统数据一致性同时&#xff0c;保障系统稳定性 二、流程设计 三、数据库设计 本次示例仅涉及商品表、订单表&#xff0c;这里分享数…

2024可信数据库发展大会:TDengine CEO 陶建辉谈“做难而正确的事情”

在当前数字经济快速发展的背景下&#xff0c;可信数据库技术日益成为各行业信息化建设的关键支撑点。金融、电信、能源和政务等领域对数据处理和管理的需求不断增加&#xff0c;推动了数据库技术的创新与进步。与此同时&#xff0c;人工智能与数据库的深度融合、搜索与分析型数…

《Towards Black-Box Membership Inference Attack for Diffusion Models》论文笔记

《Towards Black-Box Membership Inference Attack for Diffusion Models》 Abstract 识别艺术品是否用于训练扩散模型的挑战&#xff0c;重点是人工智能生成的艺术品中的成员推断攻击——copyright protection不需要访问内部模型组件的新型黑盒攻击方法展示了在评估 DALL-E …

AI算法18-最小角回归算法Least Angle Regression | LARS

​​​ 最小角回归算法简介 最小角回归&#xff08;Least Angle Regression, LAR&#xff09;是一种用于回归分析的统计方法&#xff0c;它在某些方面类似于最小二乘回归&#xff0c;但提供了一些额外的优点。最小角回归由Bradley Efron等人提出&#xff0c;主要用于处理具有…

【鸿蒙学习笔记】舜和酒店项目开发

这里写目录标题 前期准备1. 环境准备2. 开发工具准备 创建项目1. 使用 deveco-studio 创建 ShunHeHotel 项目2. 把ShunHeHotel 项目使用git进行版本控制3. 提交第1个commit&#xff0c;Alt0 → 输入commit message → 提交4. 查看已经提交的第一个提交5. gitcode 创建同名远程项…

数据库系统概论:关系型数据库系统

引言 如今最为重要的数据模型便是关系模型。关系数据库就是支持关系模型的数据库系统&#xff08;Relational Database Management System, RDBMS&#xff09; 关系模型可以简单理解为二维表格模型&#xff0c;一个关系型数据库就是由二维表及其之间的关系组成的一个数据组织。…

1、常用模块讲解(simulink仿真)

1、常用模块讲解&#xff08;simulink仿真&#xff09; Simulate有很多库 进入simulink 命令行simulink再回车 &#xff0c;或点击菜单栏 Export model to 可以将高版本保存为低版本 1&#xff0c;在MATLAB主界面&#xff0c;新建编辑器&#xff0c; a1:100; bsin(a*0.2); pl…

argparse部分用法

文章目录 一、一个简单的示例1.导入模块2.创建解析器3.添加参数4.解析参数5.使用解析的参数6.完整程序7.运行 二、更多用法1.ArgumentParser对象创建时的参数2.add_argument()的参数&#xff08;1&#xff09;name&#xff1a;名称1&#xff09;位置参数2&#xff09;可选参数3…

priority_queue的使用与模拟实现

目录 priority_queue的使用 priority_queue的介绍 priority_queue的定义方式 priority_queue成员函数的介绍 priority_queue的模拟实现 1&#xff1a;堆的向上调整算法 2&#xff1a;堆的向下调整算法 两种算法的比较与各自最佳使用 priority_queue的模拟实现 priorit…

使用VMware虚拟机安装kali 2019

一、下载kali linux镜像 下载 kali Linux的ISO镜像文件 网盘链接&#xff1a;https://pan.baidu.com/s/1GRtJxGBlqFfmU24HLEy3-g?pwd57u3 提取码&#xff1a;57u3 二、安装并配置 Kali Linux 新建虚拟机 在虚拟机创建向导中&#xff0c;选择经典配置 选择下载好的kali镜…

细说MCU用定时器控制ADC采样频率的实现方法并通过Simulink查看串口输出波形

目录 一、硬件工程 二、建立Simulink模型 1.安装MATLAB和Simulink 2.建立Simulink模型 三、代码修改 1.修改回调函数 2.产看结果 3.完整的main.c 本文作者的文章 细说MCU用定时器控制ADC采样频率的实现方法-CSDN博客 https://wenchm.blog.csdn.net/article/details/…

WSL-Ubuntu20.04环境使用YOLOv8 TensorRT推理加速

在阅读本章内容之前,需要把部署环境以及训练环境都安装好。 1.TensorRTX下载 这里使用Wang-xinyu大佬维护的TensorRTX库来对YOLOv8进行推理加速的演示,顺便也验证一下前面环境配置的成果。 github地址:GitHub - wang-xinyu/tensorrtx,下载后放到wsl的路径下,我这里放在/h…

JavaScript日期对象倒计时案例

思路&#xff1a;1.先求出当前时间的总毫秒数 2.再求出所需要求的时间的总毫秒数 3.用所求时间的减去当前时间的可得到倒计时剩余时间 4.最后将所求的倒计时剩余时间转换为天&#xff0c;小时&#xff0c;分钟&#xff0c;秒即可 <!DOCTYPE html> <html lang"en…

Java并发04之线程同步机制

文章目录 1 线程安全1.1 线程安全的变量1.2 Spring Bean1.3 如果保证线程安全 2 synchronized关键字2.1 Java对象头2.1.1 对象组成部分2.1.2 锁类型2.1.3 锁对象 2.2 synchronized底层实现2.2.1 无锁状态2.2.2 偏向锁状态2.2.3 轻量级锁状态2.2.4 重量级锁2.2.5 锁类型总结2.2.…

【动态规划】力扣2266.统计打字方案数

Alice 在给 Bob 用手机打字。数字到字母的 对应 如下图所示。在这里插入图片描述 为了 打出 一个字母&#xff0c;Alice 需要 按 对应字母 i 次&#xff0c;i 是该字母在这个按键上所处的位置。 比方说&#xff0c;为了按出字母 ‘s’ &#xff0c;Alice 需要按 ‘7’ 四次。…

C++:类的默认成员函数

默认成员函数就是⽤⼾没有显式实现&#xff0c;编译器会⾃动⽣成的成员函数称为默认成员函数。⼀个类&#xff0c;我们不写的情况下编译器会默认⽣成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个。 定义一个空类&#xff1a; class A { }; 经过编译器…

Etsy开店指南:分步指南与防封技巧

您的Etsy帐户在注册后不久就被封了吗&#xff1f;如果是这样&#xff0c;您在设置Etsy帐户时就已经错误了&#xff0c;其实这其中还是有很多细节需要注意&#xff1b;本文全面讲解了如何逐步创建帐户&#xff0c;如果你也正在准备&#xff0c;那就继续看吧&#xff01; 一、在开…