Day10补代码随想录 理论基础|232.用栈实现队列|225.用队列实现栈|20.有效的括号|1047.删除字符串中的所有相邻重复项
栈和队列理论基础
抽象认识
- 栈是先进后出(FIFO),队列是先进先出(LIFO)
- 队首(先进))队尾(后进)
- 栈顶(后进)栈底(先进)
- 栈(Stack)
- 只在一端进行进出操作(只在一端进一端出)
- 像个篮球框,取用篮球从一端进出。
-
/进栈 int a[1000];//足够大的栈空间 int top=-1;//栈的初始化,栈顶位置标记 for(i=0;i<10;i++){a[++top]=i;//先对top+1,再录入位置,使用++top为了防止最后一次循环赋值后top依旧进行+1,使得top指向了栈外的空数组。 } /出栈 for(i=0;i<10;i++){ print("%d",a[top--]);}
- 队列(Queue)
- 在两端分别进行进和出的操作(一端进一端出)
- 食堂排队,从后面排队,前面买饭离开。
-
//QQ号,有10个数字的排列,排序为奇数的数字取出排列;排序为偶数的数字放入队尾重新报号,组成QQ号。 int a[100]={1,2,3,4,5,6,7,8,9,0},head,tail; //队头队尾 head=0; tail=10;//标记的是最后一个元素后面的空元素 while(head<tail){printf("%d",a[head]);//奇数离开队伍head++;a[tail]=a[head];//偶数放在队尾tail++;//补长队尾head++;//减少队头}
JAVA中的栈和队列
- 栈(Stack) Stack类位于java.util包中
- 基本操作
- push(E item):将元素压入栈顶。
- pop():移除并返回栈顶的元素。
- peek():查看栈顶的元素,但不移除。
- isEmpty():判断栈是否为空。
- 低层实现:基于一个动态数组(Vector)来实现的,和C++类似,可以通过扩展Vector来管理栈中的元素。
- 基本操作
- 队列(Queue) Queue接口
- 常见的实现类
- LinkedList:提供队列的标准实现
- PriorityQueue:优先队列,根据元素的优先级顺序出队。
- ArrayDeque:基于数组的双端队列。
- 基础操作
- add(E e):将元素添加到队尾
- remove():移除并返回队首的元素
- peek():查看队首的元素,但不移除。
- isEmpty():判断队列是否为空
- 底层实现:默认的队列实现是LinkedList,基于双向链表来实现队列的入队和出队操作。ArrayDeque是基于数组的实现,通常性能更好。
- 常见的实现类
几个问题
- Java中的Stack是容器吗?
- 是,Stack是一个继承自vector类的容器。vector是一个可动态扩展的数组,实现了List接口。Stack类本身是一个容器类,提供了栈(LIFO)操作,由于
Stack
继承自Vector
,所以它本质上也继承了Vector
的所有特性,包括动态调整大小和随机访问等。然而,Stack
主要用来模拟栈的行为,提供了栈特有的操作,但并不暴露所有Vector
提供的操作。
- 是,Stack是一个继承自vector类的容器。vector是一个可动态扩展的数组,实现了List接口。Stack类本身是一个容器类,提供了栈(LIFO)操作,由于
- 我们使用的stack是属于什么?
- JAVA标准库(JDK),位于java.util,
- stack类是继承自Vector的一个类,设计用于支持栈(LIFO)行为。
- JAVA的stack是如何实现的?
- Stack是通过继承Vector类来实现的。Vector是一个动态数组,可以自动扩展它的容量。
- Stack通过push()和pop()方法来操作Vector中的元素,以实现栈的LIFO行为。
- stack提供迭代器来遍历stack空间吗?
- 是的,但不推荐使用。
- Stack提供了iterator()方法来获取一个迭代器,从而遍历栈中的元素、但是不符合栈的设计哲学,因为栈是符合先进后出原则,允许迭代器遍历栈中 元素会破坏这一原则。
- 由于栈的特性,只允许访问栈顶元素,允许迭代的做法违背了栈的设计原则,因此并不推荐使用Stack类,推荐使用Deque(双端队列)或ArrayDeque来代替Stack,这些类支持栈和队列的操作,并且不会提供队元素的遍历行为。
- 在java中,没有缺省容器的概念,栈类和队列类都是固定的,不能更换低层容易,Java中的Stack类的底层实现是固定的。
232.用栈实现队列
题目
https://leetcode.cn/problems/implement-queue-using-stacks/description/
使用栈实现队列的下列操作:
push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。
- 你只能使用标准的栈操作 – 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
- 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
- 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
思路
-
思路
- 用****2个栈(入栈)****来改变出栈顺序
- 入栈要全部放在出栈里,模拟队列的行为(如果出栈是空的)
- 队列是先进先出,栈是先进后出,那么就让数先入栈,再将入栈的数移动到出栈里,开口不变。
- 如果要弹出,看看出栈是否为空,如果为空,把所有元素加倒出栈里。
- 用****2个栈(入栈)****来改变出栈顺序
-
代码思路
- 写清各个接口的返回类型
- 初始化入栈和出栈类,创建入栈和出战的对象。
-
class MyQueue{//声明入栈和出栈Stack<Integer> stackIn;Stack<Integer> stackOut;//Initialize public MyQueue(){stackIn=new Stack<>();stackOut=new Stack<>();}//将一个元素放入队列的尾部public void push(int x){stackIn.push(x);//队列从入栈进入}//从队列首部移除元素public int pop(){//队列中的先进先出,就是取出一个元素并返回它。dumpstackIn();//在出栈放入栈pop出来的数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());//放入栈pop出来的数}} }/*** Your MyQueue object will be instantiated and called as such:* MyQueue obj = new MyQueue();* obj.push(x);* int param_2 = obj.pop();* int param_3 = obj.peek();* boolean param_4 = obj.empty();*/
总结
- 声明入栈和出栈
Stack<Integer>
stackIn;
Stack<Integer>
stackOut; - 创建入栈和出栈的对象,stackIn=new Stack<>();stackOut=new Stack<>();
- return stackOut.peek();//默认返回栈顶,但不移除它
225.用队列实现栈
题目
https://leetcode.cn/problems/implement-stack-using-queues/description/
https://programmercarl.com/0225.%E7%94%A8%E9%98%9F%E5%88%97%E5%AE%9E%E7%8E%B0%E6%A0%88.html
【惯性思维用两个队列来模拟栈,其实只用一个队列就可以模拟栈了】
使用队列实现栈的下列操作:
- push(x) – 元素 x 入栈
- pop() – 移除栈顶元素
- top() – 获取栈顶元素
- empty() – 返回栈是否为空
注意:
- 你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
- 你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
- 你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)
- 【单向队列】
思路
- 我的思路
- 队列是先进先出,我们让它先进后出,改变出口方向,每当队列满了之后,从列尾出去
- Karl思路
- 队列是先进先出的顺序,如果用两个队列,将一个队列移动到另一个队列中时,先进先出的顺序还是没有改变。
- 栈pop的是栈顶元素(后进),队列pop的是队首,我们让栈顶元素(后进)元素pop到栈尾,假设栈有n个元素,每次让栈的栈底元素pop出来,需要将前n-1个元素放入到栈底后面。
- 代码
class MyStack {Queue<Integer> queue;//Queue是个接口public MyStack() {queue=new LinkedList<>();//LinkedList是Queue的一个实现类 }public void push(int x) {queue.add(x);//将元素添加到队尾,相当于栈整体移动到队列了 }public int pop() {rePosition();return queue.poll();//移除并返回栈首元素}public int top() {rePosition();int result=queue.poll();//先移除队首(实际是之前的队尾,即后进)queue.add(result);//后进在栈顶,返回return result;}public boolean empty() {return queue.isEmpty();}//将队列前面的元素加入到队列末尾public void rePosition(){int size=queue.size();size--;//需要将size-1个元素移动到队尾while(size-->0)//在每次循环后,将size-1,只要size>0就继续queue.add(queue.poll());//移除并返回队首元素,知道前size-1个元素全部返回} }/*** Your MyStack object will be instantiated and called as such:* MyStack obj = new MyStack();* obj.push(x);* int param_2 = obj.pop();* int param_3 = obj.top();* boolean param_4 = obj.empty();*/
总结
- size()和length的使用范围
- size()是方法,length是属性
- size():用于动态大小的集合类;Map的键值对数量
- length:固定长度的数组,字符串
- 注意事项
-
接口和实现类
- Queue
<Integer>
queue;//Queue是个接口 - queue=new LinkedList<>();//LinkedList是Queue的一个实现类
- Queue
-
queue的一些用法
- queue.add(x) 将元素加入队尾
- queue.poll() 移除并返回队首元素
-
top()方法需要多练习,很绕。
-
20.有效的括号
题目
https://programmercarl.com/0020.%E6%9C%89%E6%95%88%E7%9A%84%E6%8B%AC%E5%8F%B7.html
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 注意空字符串可被认为是有效字符串。
示例 1:
- 输入: “()”
- 输出: true
示例 2:
- 输入: “()[]{}”
- 输出: true
示例 3:
- 输入: “(]”
- 输出: false
示例 4:
- 输入: “([)]”
- 输出: false
示例 5:
- 输入: “{[]}”
- 输出: true
思路
- 我的思路
- 思路很混乱,怎么能在栈和队列中实现这些
- Carl
- 三种不匹配的情况
- 字符串里的左方向的括号多余了,不匹配。
- 括号没有多余,但是括号的类型没有匹配上。
- 右方向的括号多余了,不匹配
- 字符串里的左方向的括号多余了,不匹配。
- 三种不匹配的情况
- 代码思路
- 如果是奇数,一定可以发现不匹配字符。
- for循环
- if 遇到(,在栈中加)
- 提前准备比较匹配
- else if { ,在栈中加}
- elseif [,在栈中加]
- 【情况2,3】elseif 栈空(情况3)||不匹配(情况2) return false;相等情况弹出。
- 【情况1】 遍历到最后一个了,如果不是空栈,return false;
- 代码
class Solution {public boolean isValid(String s) {Deque<Character> deque=new LinkedList<>();//声明并创建实例char ch;for(int i=0;i<s.length();i++){ch=s.charAt(i);//提前匹配if(ch=='('){deque.push(')');}else if(ch=='{'){deque.push('}');}else if(ch=='['){deque.push(']');}else if(deque.isEmpty()||deque.peek()!=ch){ //情况2,3return false;}else{//如果是右括号判断是否和栈顶元素匹配deque.pop();}}return deque.isEmpty();} }
总结
- string要转换为char,才能比较
- 注意,情况2,3先判断栈空【情况3】
1047.删除字符串中的所有相邻重复项
题目
https://programmercarl.com/1047.%E5%88%A0%E9%99%A4%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E7%9B%B8%E9%82%BB%E9%87%8D%E5%A4%8D%E9%A1%B9.html
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
- 输入:“abbaca”
- 输出:“ca”
- 解释:例如,在 “abbaca” 中,我们可以删除 “bb” 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa” 可以执行重复项删除操作,所以最后的字符串为 “ca”。
提示:
- 1 <= S.length <= 20000
- S 仅由小写英文字母组成。
【栈的经典应用,栈喜欢做这种消除的操作,栈帮助记录了遍历数组当前元素的时候,前一个元素是什么】
思路
- 我的思路
- 难点,删除完bb后aa又靠近了。迭代。
- 每遍历一个元素,
-
如果有前一个元素,把他的前一个元素储push在栈中。
- 比较它和前一个元素,如果匹配,就删除字符串里的这个元素和前一个元素,不匹配就pop。
-
else if
- continue.
-
- Carl思路
- 消消乐,
- if 栈是空的||不匹配,那么放入当前元素
- else if 消除 pop弹出
- 最后要把栈中的字符串翻转过来
- 消消乐,
- 代码
class Solution {public String removeDuplicates(String s) {ArrayDeque<Character> deque=new ArrayDeque<>();char ch;for(int i=0;i<s.length();i++){ch=s.charAt(i);//如果栈空或不匹配栈顶if(deque.isEmpty()||deque.peek()!=ch){deque.push(ch);}else{//匹配就删掉deque.pop();}}String str="";//剩余的元素while(!deque.isEmpty()){//全pop出去str=deque.pop()+str;//先pop出去的放在前面,恢复正序}return str;} }
总结
-
ArrayDeque 是JAVA中的双端队列数据结构,既可以用作栈,也可以用做队列
- 栈
- push()
- pop()
- 队列
- add()
- poll()
//ArrayDeque会比LinkedList在除了删除元素这一点外会快一点//参考:https://stackoverflow.com/questions/6163166/why-is-arraydeque-better-than-linkedlist
- 栈
-
低级错误,ch=s.charAt(i); 里面是string s 的第i个,而不是直接ch=s.charAt(s);
相关文章:

Day10补代码随想录 理论基础|232.用栈实现队列|225.用队列实现栈|20.有效的括号|1047.删除字符串中的所有相邻重复项
栈和队列理论基础 抽象认识 栈是先进后出(FIFO),队列是先进先出(LIFO) 队首(先进))队尾(后进)栈顶(后进)栈底(先进) 栈(Stack) 只在一端进行进出操作(只在一端进一端出)像个篮球框,取用篮球从一端进出。 /进栈 int a[1000];//足够大的栈空间 int top-1…...

【Devops】什么是Devops?(Development+Operations)和运维的区别?
DevOps(Development Operations)是一种将开发(Development)和运维(Operations)团队结合在一起的文化和实践,目的是通过自动化、协作和持续反馈来加快软件的开发、部署和运维的周期,…...

基于NodeMCU的物联网电灯控制系统设计
最终效果 基于NodeMCU的物联网电灯控制系统设计 小程序关灯 上图展现了小程序关灯过程的数据传输过程:用户下达关灯指令→小程序下发关灯指令→MQTT服务器接收关灯指令→下位机接收与处理关灯指令。 项目介绍 该项目是“物联网实验室监测控制系统设计(…...

Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02
在嵌入式开发中,I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,广泛应用于与外设(如 EEPROM、传感器、显示屏等)进行数据交换。AT24C02 是一种常见的 I2C EEPROM 存储器,它提供 2Kbit…...

Linux应用软件编程-多任务处理(线程)
线程:轻量级的进程,线程的栈区独立(8M),与同一进程中的其他线程共用进程的堆区,数据区,文本区。 进程是操作系统资源分配的最小单位;线程是cpu任务调度的最小单位。 1. 线程的创建…...

VITUREMEIG | AR眼镜 算力增程
根据IDC发布的《2024年第三季度美国AR/VR市场报告》显示,美国市场AR/VR总出货量增长10.3%。其中,成立于2021年的VITURE增长速度令人惊艳,同比暴涨452.6%,成为历史上增长最快的AR/VR品牌。并在美国AR领域占据了超过50%的市场份额&a…...

Jenkins管理多版本python环境
场景:项目有用到python3.8和3.9,python环境直接安装在jenkins容器内。 1、进入jenkins容器 docker exec -it jenkins /bin/bash 2、安装前置编译环境 # 提前安装,以便接下来的配置操作 apt-get -y install gcc automake autoconf libtool ma…...

Flutter富文本实现学习
Flutter 代码如何实现一个带有富文本显示和交互的页面。 前置知识点学习 RealRichText RealRichText 和 ImageSpan 不是 Flutter 框架中内置的组件,而是自定义的组件或来自第三方库。这些组件的实现可以提供比标准 RichText 更丰富的功能,比如在富文本…...

如何解决 OpenAI API 连接问题:降级 urllib3 版本
如何解决 OpenAI API 连接问题:降级 urllib3 版本 在使用 OpenAI API 时,很多开发者可能会遇到连接问题,特别是在使用 Python 代码与 OpenAI 进行交互时。常见的错误包括 ProxyError、SSLError 和 MaxRetryError,它们通常表示在通…...

【C语言】库函数常见的陷阱与缺陷(三):内存分配函数[4]--free
C语言中的free函数用于释放之前通过malloc、calloc或realloc动态分配的内存。然而,在使用free函数时,开发者可能会遇到一些陷阱和缺陷。 一、功能与用法 free 函数是 C 语言中用于释放动态分配内存的关键函数。在程序使用 malloc、calloc 或 realloc 等函数在堆上分配了内存…...

论文分享 | PromptFuzz:用于模糊测试驱动程序生成的提示模糊测试
大语言模型拥有的强大能力可以用来辅助多种工作,但如何有效的辅助仍然需要人的精巧设计。分享一篇发表于2024年CCS会议的论文PromptFuzz,它利用模型提示生成模糊测试驱动代码,并将代码片段嵌入到LLVM框架中执行模糊测试。 论文摘要 制作高质…...

AWS K8s 部署架构
Amazon Web Services(AWS)提供了一种简化的Kubernetes(K8s)部署架构,使得在云环境中管理和扩展容器化应用变得更加容易。这个架构的核心是AWS EKS(Elastic Kubernetes Service),它是…...

JavaSE笔记(四)
Java泛型与集合类 在前面我们学习了最重要的类和对象,了解了面向对象编程的思想,注意,非常重要,面向对象是必须要深入理解和掌握的内容,不能草草结束。在本章节,我们会继续深入了解,从我们的泛型开始,再到我们的数据结构,最后再开始我们的集合类学习。 走进泛型 为…...

C语言基础——指针(5)
一. 函数指针变量 1. 函数指针变量的定义: 类比数组指针变量,数组指针变量是存放数组地址的变量,那么同理,函数指针变量就是存放函数地址的变量。 2. 创建函数指针变量: 函数是有地址的࿰…...

curl+openssl 踩坑笔记
curl编译:点击跳转 踩坑一 * SSL certificate problem: unable to get local issuer certificate * closing connection #0 curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.se/docs/sslcerts.html …...

Unity 实现Canvas显示3D物体
新建一个UI相机,选择渲染层为UI 将主相机的渲染层去掉UI层 、 将Canvas的RenderMode设置为Screen Space - Camera,将RenderCamera设置为UI相机 新建3D物体的UI父物体,并将3D物体的层级设置为UI层 适当的放缩3DObjParent,让3D物体能显示出来…...

【Docker命令】如何使用`docker exec`在容器内执行命令
大家好,今天我们来聊聊Docker容器管理中的一个非常有用的命令:docker exec。在日常工作中,我们经常需要在运行中的Docker容器内执行各种命令,docker exec正是帮助我们实现这一需求的利器。下面我将通过一个简单的例子,…...

NetSuite Formula(HTML)超链打开Transaction
当Saved Search作为Sublist应用在Form时,如果Document Number是Group过的,则会出现如下超链失效的情况。 解决办法: 可以利用Saved Search中的Formula(HTML)功能来构建超链,用于打开Transaction。 以下图…...

【React】- 跨域PDF预览、下载(改文件名)、打印
我们经常会碰到跨域来方位PDF,同时需要下载、打印的需求,通常由于浏览器的安全策略,可以预览,但是下载和打印可能会受限,这时候怎么办呢? 1.创建一个隐藏的标签 要下载 iframe 中的 PDF 文件,…...

git clone ssh 设置代理
Linux配置方法 编辑 ~/.ssh/config 文件 Host github.com Hostname github.com ProxyCommand nc -v -x 127.0.0.1:1080 %h %pwindows配置方法 编辑 C:\Users\当前用户名.ssh\config 文件 Host github.com Hostname github.com ProxyCommand connect -S 127.0.0.1:1080 %h %…...

RK3568平台(USB篇)USB网络共享
使用RK的USB网络共享,在内核里面已经有了,这不需要自己写驱动程序,只需要把内核自带的USB网络共享的驱动添加上去即可。 一.RNDIS 协议简介 RNDIS 是微软定义的一种协议,它允许通过 USB 接口实现网络连接。通过 RNDIS,USB 设备可以充当网络适配器,允许主机通过 USB 与设…...

vite 打包时:JavaScript heap out of memory(内存溢出)
出错原因分析: 执行命令 npm run build 时出现以下错误提示: vite v3.2.7 building for production... 11:22:34 transforming (3) src\main.tsWARN Browserslist: caniuse…...

【服务器学习专栏 1.2 -- 带外管理】
请阅读 嵌入式学习必备专栏 文章目录 Overview服务器带外管理BMC 介绍BMC 特点BMC 工作原理 Overview 从技术的角度,网络管理可分为带外管理(out-of-band)和带内管理(in-band)两种管理模式。 带内管理,是指…...

微服务のGeteWay
目录 概念: 三大核心: 工作流程: 9527网关如何做路由映射: GetWay高级特性: 按服务名动态路由服务: 断言Route Predicate Factories : 获取当前时区时间: After Route &…...

html+css+js网页设计 美食 美食家6个页面
htmlcssjs网页设计 美食 美食家6个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1…...

IntelliJ Idea常用快捷键详解
文章目录 IntelliJ Idea常用快捷键详解一、引言二、文本编辑与导航1、文本编辑2、代码折叠与展开 三、运行和调试四、代码编辑1、代码补全 五、重构与优化1、重构 六、使用示例代码注释示例代码补全示例 七、总结 IntelliJ Idea常用快捷键详解 一、引言 在Java开发中ÿ…...

服务器虚拟化:它是什么以及有什么好处?
运行虚拟服务器有助于创建更高效的 IT 基础架构。 随着业务每天收集的数据量逐年激增,传统的物理服务器已经无法单独满足业务需求。 相反,许多组织正在转向虚拟化的力量。 这是我们创建物理实体的虚拟版本的过程,在计算中,通常指…...

Python爬虫完整代码拿走不谢
对于新手做Python爬虫来说是有点难处的,前期练习的时候可以直接套用模板,这样省时省力还很方便。 使用Python爬取某网站的相关数据,并保存到同目录下Excel。 直接上代码: import re import urllib.error import urllib.request…...

MLA:多头潜在注意力
MLA:多头潜在注意力 多头潜在注意力(MLA)机制是一种在深度学习模型中用于处理序列数据的注意力机制的改进形式,以下是对其原理和示例的详细介绍: 原理 低秩键值联合压缩:MLA机制利用低秩键值联合压缩来消除注意力模块中的某些计算,从而提高模型的运行速度和性能。在传…...

阿里云大模型ACP高级工程师认证模拟试题
阿里云大模型ACP高级工程师认证模拟试题 0. 引言1. 模拟试题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题单选题单选题多选题多选题单选题多选题单…...