【leetcode 力扣刷题】栈和队列的基础知识 + 栈的经典应用—匹配

栈和队列的基础知识 + 栈的经典应用—匹配

  • 栈和队列基础知识
    • 232. 用栈实现队列
    • 225. 用队列实现栈
  • 20. 有效的括号
  • 1047. 删除字符串中的所有相邻重复项

栈和队列基础知识

数据结构课程介绍线性结构的时候,介绍有线性表、链表、栈和队列。线性表,比如array、vector可以直接用下标定位到相应元素,但是删除元素时,需要移动其他元素,不能原地删除;链表不能用下标定位,是通过指针来定位到相应元素的地址空间,但添加or删除元素时,时间复杂度是O(1)的;栈和队列是比较特殊的线性结构,特殊在于栈和队列中的元素不能随意的访问——对于栈,只能访问栈顶元素(用top()方法),只能向栈顶添加元素(用push()方法),只能从栈顶取元素(用pop()方法)。我们可以把栈看作是一个瓶子,依次从瓶口(即栈顶)扔进去乒乓球,倒出来的时候不能从瓶底拿,也只能从瓶口,而且拿出来的顺序跟放进去的是反的,即先进后出,后进先出;对于队列,则有两个开口,可以看作有两个口的管道,从一个方向把球塞进去(push()),从另外一个方向取出来(pop()),那么取出来的顺序还是和塞进去的顺序一样的,即先进先出,后进后出
在这里插入图片描述
C++ STL中stack和queue实际上并不是容器,而是容器适配器。比如声明一个stack变量的语句是stack<typename T, typename Container = deque<T>> ,如果不说明是用什么容器,就默认用deque,如果说明了用vector,用的就是vector——stack<int, vector<int> > mystk
C++STL中stack的成员函数及作用如下表:

成员函数作用
size()返回堆栈中元素的数量
empty()检查堆栈是否为空。如果堆栈为空,则返回true;否则,返回false
top()返回堆栈顶部元素的引用,但不会删除该元素;如果堆栈为空,则行为是未定义的
pop()从堆栈的顶部移除元素,但不返回其值;如果堆栈为空,则行为是未定义的
push(const T& value)将元素插入到堆栈的顶部;参数value是要插入的元素的值
emplace(Args&&... args)通过在堆栈的顶部构造一个新的元素来插入元素;参数args是用于构造元素的参数

这里注意push()和emplace()两个成员函数都能实现在向栈顶压入一个元素,但是push要先创建value的副本,而emplace是直接插入元素。总之emplace效率更高。……但我不是很懂……
queue的成员函数及作用如下表:

成员函数作用
empty()检查队列是否为空。如果队列为空,则返回true;否则,返回false
size()返回队列中元素的数量
front()返回队列头部的元素的引用,但不会删除该元素;如果队列为空,则行为是未定义的
back()返回队列尾部的元素的引用,但不会删除该元素;如果队列为空,则行为是未定义的
pop()从队列的头部移除元素,但不返回其值;如果队列为空,则行为是未定义的
push(const T& value)将元素插入到队列的尾部;参数value是要插入的元素的值
emplace(Args&&... args)通过在队列的尾部构造一个新的元素来插入元素;参数args是用于构造元素的参数

232. 用栈实现队列

题目链接:232. 用栈实现队列
题目内容:
在这里插入图片描述
思路:栈是先入后出的,push和pop都只能在栈顶;但是队列是对头方向pop,队尾方向实现push。根据这俩的特性,可以知道对于push操作是没有差异的,直接末尾push就好。对于pop,先入栈的元素在栈的底端,如何才能先出栈?——因为题目中说了可以用两个栈,那么一个栈A用作入队,一个栈B用作出队。压入栈A中的元素,再依次取出并压入栈B,栈B的出栈顺序就和队列的出队顺序一样了。比如下图,依次入队是(出队也是)1,2,3,4,先放入栈A,再将栈A的元素依次取出并放入栈B,此时栈B内元素的出栈顺序也是1,2,3,4了。
在这里插入图片描述
因此出队pop()操作就是将栈A的元素全部依次取出并放入栈B中。 但是当栈B不为空的时候呢? 这里需要意识到栈B中所有的元素都是在栈A之前的,如果栈B不为空,就直接pop栈顶元素,即为队头元素;如果栈B为空,再从栈A中取出元素放入栈B。
代码如下(C++):

class MyQueue {
private://两个栈,一个用于出队,一个用于入队stack<int> InStack;stack<int> OutStack;
public:MyQueue() {}//push直接在入队栈的栈顶push就好    void push(int x) {InStack.push(x);}int pop() {//如果出堆栈为空,先将入队栈的元素依次取出并push进出队栈if(OutStack.empty()){while(!InStack.empty()){OutStack.push(InStack.top());InStack.pop();}}//直接从出队栈栈顶pop,即为队头元素int result = OutStack.top();OutStack.pop();return result;}//peek是返回队头元素但是不删除,可以复用pop的代码,只是需要push回去int peek() {int result = this->pop();OutStack.push(result);return result;}//入队栈和出队栈都为空才为空bool empty() {if(InStack.empty() && OutStack.empty())return true;return false;}
};

225. 用队列实现栈

题目链接:225. 用队列实现栈
题目内容:
在这里插入图片描述
前面用栈实现队列里说到,push的时候直接push就行,现在用队列实现栈也是,push的时候直接在队列的末尾push就好。题目说用两个队列,实际上用一个队列即可。用栈实现队列的时候两个栈各有作用,一个入队栈一个出队栈,将一个栈的元素依次取出再push到另外一个栈能够实现出栈顺序的颠倒。但是对于队列,一个队列的元素依次取出再放入另外一个队列,实际还是一样的顺序,而这个操作可以通过将队头元素pop()后直接push到队尾来实现,因此只需要一个队列即可。
所以,对于栈的pop,需要找到队列的末尾元素,从队头方向,依次取出元素再push到末尾,直到之前的队尾元素现在在队头了【循环size-1次】,直接pop。
代码如下(C++):

class MyStack {
private://用于实现栈的队列,只需要一个queue<int> que1;
public:MyStack() {}//直接队列末尾push即可void push(int x) {que1.push(x);}//将队头元素pop再push到队尾,循环size-1次,栈顶的元素就到了队头了int pop() {int size = que1.size() - 1;int top;//循环size-1次while(size){top = que1.front();que1.pop();que1.push(top);size--;}//队头元素top = que1.front();que1.pop();return top;        }//栈顶即队尾元素,queue有直接取队尾元素的成员函数int top() {return que1.back();}//队列不为空,栈就不为空;队列空了栈也空了    bool empty() {return que1.empty();}
};

20. 有效的括号

题目链接:20. 有效的括号
题目内容:
在这里插入图片描述
有效括号可以概括为两点:

  • 每个左括号都有一个对应的类型的右括号闭合;每个右括号都能与一个对应类型的左括号闭合;即每种类型的左括号和右括号数量要一样,有2个"(“,就得有2个”)";
  • 左括号必须以正确的顺序闭合,比如"( [ ) ]“就是不正确的,应该让”["先闭合;
    基于以上两个特点,我们可以用栈来完成这个题目。是左括号"(" “[” "{"就入栈;是右括号就判断后栈顶的左括号是否匹配【保证左括号以正确的顺序闭合——内层的括号先闭合】。

如果最终多了右括号或者左括号就说明是不匹配的。
代码实现(C++):

class Solution {
public:bool isValid(string s) {//括号数量是奇数一定不能正确匹配if(s.size() & 1)return false;stack<char> buff; //存左括号for(int i = 0; i < s.size(); i++){//是左括号,就直接入栈if(s[i] == '(' || s[i] == '[' || s[i] == '{')buff.push(s[i]);//是右括号,并且左括号栈不为空else if(!buff.empty()){//如果和栈顶括号匹配if(s[i] == ')' && buff.top() == '('||s[i] == ']' && buff.top() == '['||s[i] == '}' && buff.top() == '{') buff.pop(); //栈顶左括号出栈,表示已经匹配了else //和栈顶左括号不匹配直接返回falsereturn false;}else //是右括号,但是左括号栈为空,直接返回falsereturn false;}//右括号匹配完了,如果栈内还要左括号返回false,如果左括号栈也为空,返回truereturn buff.empty() ? true : false;}
};

可以用map来存左右括号的对应关系,简化代码:

class Solution {
public:bool isValid(string s) {if(s.size() & 1)return false;unordered_map <char,char> pairs;//左右括号对应关系pairs['('] = ')';pairs['['] = ']';pairs['{'] = '}';//存储左括号stack<char> zuo;for(char ch : s){//左括号直接入栈if(pairs.count(ch))zuo.push(ch);//右括号else{//左括号为空,或者栈顶左括号和当前右括号不匹配if(zuo.empty() || ch != pairs[zuo.top()])return false;//相反情况就是匹配,直接栈顶左括号出栈zuo.pop();}}return zuo.empty();}
};

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

题目链接:1047. 删除字符串中的所有相邻重复项
题目内容:
在这里插入图片描述
根据给出的例子可以看出,abbaca删除bb后,又会出现aa可以删除,因此还是用栈这个结构来实现:

  • 遍历字符串,如果当前字符和栈顶元素不同直接入栈;
  • 如果相同,该字符不保存,同时栈顶的相同元素也要删除。

这里注意,可以用string来实现,利用其pop_back()和push_back()这个类似stack操作的成员函数,在string末尾添加、删除元素。代码实现(C++):


class Solution {
public:string removeDuplicates(string s) {string ans;for(char ch : s){//如果和字符串末尾【即栈顶】元素相同,栈顶元素删除if(!ans.empty() && ans.back() == ch)ans.pop_back();//不相同就直接保存else ans.push_back(ch);}return ans;}
};

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

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

相关文章

【k8s】kube-proxy 工作模式

文章目录 Userspace模式&#xff1a;iptables模式&#xff1a;负载均衡&#xff08;Load Balancing&#xff09; LB轮询&#xff08;Round Robin&#xff09;&#xff1a;SessionAffinity&#xff1a;最少连接&#xff08;Least Connection&#xff09;&#xff1a;IP哈希&…

所有字母异位词

class Solution { public:vector<int> findAnagrams(string s, string p) {std::vector<int> idxs;// 先获取p的hash串std::string dstr getHash(p);for (int i 0; i<s.length(); i) {// 使用滑动窗口&#xff0c;每次截取p的长度串并hashstd::string sub_str…

Acwing 828. 模拟栈

Acwing 828. 模拟栈 题目要求思路讲解代码展示 题目要求 思路讲解 栈&#xff1a;先进后出 队列&#xff1a;先进先出 代码展示 #include <iostream>using namespace std;const int N 100010;int m; int stk[N], tt;int main() {cin >> m;while (m -- ){string o…

企业级数据仓库-数仓实战

数仓实战 安装包大小 安装清单 环境搭建 一、环境搭建01&#xff08;机器准备&#xff09; 准备好三台虚拟机&#xff0c;并进行修改hostname、在hosts文件增加ip地址和主机名映射 。 1、设置每个虚拟机的hostname vi /etc/sysconfig/network 修改HOSTNAMEnode02修改hostna…

将阿里云盘挂载到本地磁盘-CloudDrive工具使用教程

CloudDrive是什么&#xff1f; 支持将115、沃家云盘、天翼云盘、阿里云盘、WebDAV挂载到本地并创建本地磁盘。 CloudDrive是一个全方位的云存储管理平台&#xff0c;旨在无缝集成多个云存储服务&#xff0c;将它们统一整合到一个界面中。 使用CloudDrive&#xff0c;您可以轻松…

Nginx-高性能Web服务器

前言&#xff1a; 平时总听hex说Nginx服务器,也经常找他解决项目上的nginx配置&#xff0c;但自己一直不懂&#xff0c;不懂就学。 听他说&#xff1a;nginx最重要是 location url 配置&#xff08; 正则&#xff09;、反向代理与负载均衡&#xff0c;平时项目用这些比较多。 …

android AudioRecord

AudioRecord是Android中用于音频录制的类&#xff0c;它的主要作用是捕获来自设备麦克风或其他音频源的音频数据&#xff0c;并将其保存为PCM格式的音频流&#xff0c;以供后续处理或存储。 以下是关于AudioRecord的一些常见用途和基本使用方法&#xff1a; 作用和用途&#…

百度千帆大模型文心一言api调用

注册百度智能云账号并申请文心千帆大模型资格 https://login.bce.baidu.com/ https://cloud.baidu.com/product/wenxinworkshop 创建应用用于获取access_token 创建应用成功后,可以获取到API Key和Secret Key 获取access_token curl https://aip.baidubce.com/oauth/2.0/to…

使用电力系统稳定器 (PSS) 和静态 VAR 补偿器 (SVC) 提高瞬态稳定性(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

js实现websocket服务端和客户端

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

vue2必备知识点

1、生命周期钩子是如何实现的? 生命周期描述beforeCreatevue实例初始化后&#xff0c;数据观测&#xff08;data observer&#xff09;和事件配置之前。data、computed、watch、methods都无法访问。createdvue实例创建完成后立即调用 &#xff0c;可访问 data、computed、wat…

华为云云耀云服务器L实例评测| ultralytics最先进模型YOLOv8深度学习AI训练

目录 前言 登录服务器 安装pyhton 部署yolov8 安装Pytorch 下载权重文件 训练模型 模型使用 前言 前几期我们在云耀云服务器L实例上分别使用docker和直接在centos上部署了yolov5识别API&#xff0c;前端项目vue&#xff0c;后端项目.net Core Web Api,但是从监控图上…

unity 实现多个物体或单个物体 让其单击物体让其显示再次单击让其隐藏

unity 实现单击物体让其显示或隐藏&#xff0c;再次单击显示或隐藏 using System.Collections; using System.Collections.Generic; using Unity.Burst.CompilerServices; using UnityEngine; using UnityEngine.EventSystems; public class ToggleObjects : MonoBehaviour {…

教育领域数据可视化:点亮知识之路

教育领域一直以来都在不断进步和演变&#xff0c;而数据可视化技术正在为这一领域带来一场革命。在过去的几年里&#xff0c;教育者们越来越意识到&#xff0c;通过将教育数据转化为可视化图表和图形&#xff0c;可以更好地理解学生的表现、需求和趋势&#xff0c;从而提供更好…

看好多人都在劝退学计算机,可是张雪峰又 推荐过计算机,所以计算机到底是什么样 的?

张雪峰高考四百多分&#xff0c;但是他现在就瞧不起400多分的学生。说难听点&#xff0c;六七百分的 热门专业随便报谁不会啊&#xff1f; 计算机专业全世界都是过剩的&#xff0c;今年桂林电子科技&#xff0c;以前还是华为的校招大学&#xff0c;今年 计算机2/3待业。这个世…

Scanner类用法(学习笔记)

Scanner类用法&#xff08;学习笔记&#xff0c;后续会补充&#xff09; 1.next&#xff08;&#xff09;用法 package com.yushifu.scanner; import java.util.Scanner;//util java工具包 //Scanner类&#xff08;获取用户的输入&#xff09; Scanner s new Scanner&#…

电子词典项目

目录 目录 头文件&#xff1a;dict.h: 源文件&#xff1a;dict.c: 服务器测试文件&#xff1a;serDict.c: 客户端测试文件&#xff1a;cliDict.c: 头文件&#xff1a;dict.h: #ifndef __DICT_H__ #define __DICT_H__ #include<myhead.h> #include<sqlite3.h>#de…

Android设备关机和重启分析

一、简介 重启(reboot) 使设备重新启动,即关闭设备并重新启动它。在重启期间,设备将经历完整的启动过程,包括重新加载操作系统和其他系统组件。这可以解决一些临时的系统问题,也可以应用系统更新或配置更改。 关机(shutdown) 使设备完全关闭,即停止设备的所有运行和…

06乐观锁与悲观锁

乐观锁与悲观锁 悲观锁: 悲观锁比较适合插入数据,简单粗暴但是性能一般 乐观锁: 比较适合更新数据, 性能好但是成功率低(多个线程同时执行时只有一个可以执行成功),还需要访问数据库造成数据库压力过大 模拟乐观锁实现流程 第一步: 数据库中增加商品表t_product并插入一条数…

MySQL索引使用

验证索引效率 在讲解索引的使用原则之前&#xff0c;先通过一个简单的案例&#xff0c;来验证一下索引&#xff0c;看看是否能够通过索引来提升 数据查询性能。在演示的时候&#xff0c;我们还是使用之前准备的一张表 tb_sku , 在这张表中准备了1000w 的记录。 这张表中id为主…