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

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

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

一、用栈实现队列

题目:

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(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.xdnf.cn/news/1484051.html

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

相关文章

mac docker no space left on device

mac 上 docker 拉取镜像报错 Error response from daemon: write /var/lib/docker/tmp/docker-export-3995807640/b8464f52498789c4ebbc063d508f04e8d2586567fbffa475e3cd9afd3c5a7cf2/layer.tar: no space left on device解决&#xff1a; 增加 docker 虚拟磁盘大小。如下图

笔记 | 算法时间复杂度T(n)的计算方法

&#x1f47b; 基本思想&#xff1a;找出关键语句总执行次数 T 与 输入规模 n 的关系式 &#xff08;本博客仅提供一种解题思路与通用方法&#xff0c;具体问题请具体分析&#xff09; &#x1f47b; 类型&#xff1a;while循环 &#x1f680; 思路 找出不满足while条件时&…

fine BI 怎么制作桑基图

fine BI 怎么制作桑吉图 文章目录 fine BI 怎么制作桑吉图桑基图起源什么是桑基图一、数据二、导入帆软 BI三、组件并完成四、 外国桑基图资源&#xff08;sankeydiagram&#xff09;总结 桑基图起源 桑基图的起源可以追溯到1898年&#xff0c;‌当时Matthew Henry Phineas Ri…

《昇思25天学习打卡营第22天|生成式-Diffusion扩散模型》

Diffusion扩散模型 本文基于Hugging Face&#xff1a;The Annotated Diffusion Model一文翻译迁移而来&#xff0c;同时参考了由浅入深了解Diffusion Model一文。 本教程在Jupyter Notebook上成功运行。如您下载本文档为Python文件&#xff0c;执行Python文件时&#xff0c;请…

嵌入式系统中的GPIO控制与应用

GPIO是嵌入式系统中最常见且功能最强大的接口之一。它允许硬件工程师通过编程来配置和控制芯片上的数字引脚&#xff0c;实现输入和输出的功能。在本文中&#xff0c;我们将从理论和实践两个方面探讨GPIO的工作原理&#xff0c;并通过一个简单的示例项目来演示如何利用GPIO控制…

微软全球系统蓝屏根源与警示

本次事件是一次由CrowdStrike软件更新引发的全球性IT问题&#xff0c;主要影响运行Windows操作系统的机器。CrowdStrike是一家知名的美国网络安全公司&#xff0c;其产品Falcon Sensor旨在保护云工作负载和终端安全&#xff0c;防止黑客攻击和系统中断。然而&#xff0c;这次故…

关于springboot的@DS(““)多数据源的注解无法生效的原因

对于com.baomidou.dynamic.datasource.annotation的DS注解&#xff0c;但凡有一个AOP的修改都会影响到多数据源无法生效的问题&#xff0c;本次我是添加了方法上添加了Transactional&#xff0c;例如下图&#xff1a; 在方法上写了这个注解&#xff0c;会影响到DS("db2&qu…

Hyper-V和VMWare使用对比

图片来自互联网 1.起因 最近在学习Linux相关的知识&#xff0c;第一步当然就是装虚拟机了。之前是基于微软Hyper-V平台装的Ubuntu,用起来总是感觉卡卡的。我还一直天真的以为虚拟机都是这个样子的&#xff0c;直到用了VMWare之后…。VMWare我主要装的是VMWare16Pro&#xff0…

Xinstall教你如何利用携带参数下载,精准追踪用户来源!

在移动互联网时代&#xff0c;App的推广和运营成为了各行各业竞相追逐的焦点。然而&#xff0c;随着渠道环境的日益复杂&#xff0c;如何精准追踪用户来源、提升运营效率&#xff0c;成为了摆在推广者面前的一大难题。好在&#xff0c;Xinstall携带参数下载技术的出现&#xff…

Java学习Day7

一 &#xff1a;数组和自定义数据类型的关系 1.1 有什么关系&#xff1f; 数组可以存储自定义数据类型 1.2 数组如何存自定义数据类型&#xff1f; 数组:数据类型[] 数组名 new 数据类型[长度]&#xff1b; 定义数组和初始化 Student[] arr new Student[5]; 自定义数据类…

2、建立模型,截图,参数配置(simulink仿真)

2、建立模型&#xff0c;截图&#xff0c;参数配置&#xff08;simulink仿真&#xff09; 基本技能建模导入Word&#xff08;截图是不要用qq截图&#xff0c;不专业&#xff0c;应使用其自带截图方式&#xff09;配置参数 基本技能 1&#xff0c;参数设置 2&#xff0c;结果保…

矩阵形式的bezier曲线

本文分享一段矩阵形式的bezier代码&#xff1a; clc clear% 控制点 P [25;10;5;13]; %% 获得M矩阵 n length(P) - 1; M zeros(n1,n1); for i 1:n1for j 1:n1if(ij<n3)M(i,j) (-1)^(n -i-j2)*nchoosek(n,n-i1)*nchoosek(n-i1,j-1);elseM(i,j) 0;endend end t_temp l…

Python爬虫(1) --基础知识

爬虫 爬虫是什么&#xff1f; spider 是一种模仿浏览器上网过程的一种程序&#xff0c;可以获取一些网页的数据 基础知识 URL 统一资源定位符 uniform resource locator http: 超文本传输协议 HyperText Transfer Protocol 默认端口 80 https: 安全的超文本传输协议 security…

【洁净室】压缩气体检测参考标准:悬浮粒子、微生物、水油检测

在洁净室&#xff0c;特别是达到ISO 5或更高级别的环境中&#xff0c;维护严格的污染控制是不可或缺的。其中&#xff0c;压缩气体的质量是一个至关重要的潜在污染源。为确保压缩气体不会引入损害洁净室完整性的微粒&#xff0c;适当的气体取样成为了一项核心任务。国际标准ISO…

生活中生智慧

【 圣人多过 小人无过 】 觉得自己做得不够才能做得更好&#xff0c;互相成全&#xff1b;反求诸己是致良知的第一步&#xff1b;有苦难才能超越自己&#xff0c;开胸怀和智慧&#xff1b;不浪费任何一次困苦&#xff0c;危机中寻找智慧&#xff0c;成长自己。 把困苦当作当下…

生成式之Diffusion扩散模型

前言 基于denoising diffusion probabilistic model &#xff08;DDPM&#xff09;的扩散模型&#xff0c;该模型已在图像/音频/视频生成领域取得显著成果。目前比较受欢迎的例子包括GLIDE、DALL-E 2、潜在扩散和图像生成。生成模型的扩散概念最早在2015年由Sohl-Dickstein等人…

系统架构师考点--统一建模语言UML

大家好。今天我来总结一下面向对象的第二个考点–统一建模语言UML。 UML(统一建模语言)是一种可视化的建模语言&#xff0c;而非程序设计语言&#xff0c;支持从需求分析开始的软件开发的全过程。UML的结构包括构造块、规则和公共机制三个部分。其中考点主要集中在构造块部分&…

7.15学习游戏体验

突然意识到今天的一天基本已经过去了大半&#xff0c;自己似乎并没有做了什么&#xff0c;但是似乎好像使用了很多次搜索&#xff08;针对百度使用高级搜索&#xff0c;搜索指定的内容和格式&#xff09;&#xff0c;在这个过程中&#xff0c;并不建议使用ai&#xff0c;它的总…

c#中匿名方法的定义和使用

​ namespace _7._16day01 {internal class Program{​static void Main(string[] args){Action<string, int> t2 (x, y) > { Console.WriteLine(xy); };Action t1 () > { Console.WriteLine("lamadab"); };Func<int ,int ,int > Add (x, y) &g…

MSCKF系统学习路程

推荐课程&#xff1a; https://www.youtube.com/watch?vRDkwklFGMfo&listPLTBdjV_4f-EJn6udZ34tht9EVIW7lbeo4http://TUM MVP YOUTUBE B站中英字幕 论文&#xff1a; Robust Stereo Visual Inertial Odometry for Fast Autonomous Flight 泡泡机器人论文推荐文章