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

news2025/3/12 23:48:33

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

  • 栈和队列基础知识
    • 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 
                //和栈顶左括号不匹配直接返回false
                    return false;
                }
            else //是右括号,但是左括号栈为空,直接返回false
                return false;
        }
    //右括号匹配完了,如果栈内还要左括号返回false,如果左括号栈也为空,返回true
    return 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.coloradmin.cn/o/1007164.html

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

相关文章

室内探索无人机,解决复杂环境下的任务挑战!

前言 室内探索无人机是一种专为在室内环境中进行任务的无人机系统。相比传统的人员部署&#xff0c;室内探索无人机具有更高的灵活性和机动性&#xff0c;能够在复杂的室内环境中执行任务&#xff0c;用于未知环境的探索和特定目标的搜索。 为完成无人机室内搜索与识别等复杂…

无缝数据传输:StreamSet安装部署的最佳实践

文章目录 概要安装方法尝试安装部署方案1. 下载datacollector镜像2. 启动容器3. 访问streamsets小结 概要 StreamSets是一款流数据集成平台&#xff0c;旨在帮助用户轻松地收集、处理和传输大规模数据流。它提供了直观的界面和强大的功能&#xff0c;可用于实时数据流的提取、…

无线测温系统在运行时怎么判断配电设备出现故障?

现如今&#xff0c;电力测温方面使用无线测温系统的使用范围越来越大&#xff0c;比较熟悉的人都了解&#xff0c;传统的温度测量方式周期长、施工复杂&#xff0c;效率低&#xff0c;不便于管理&#xff0c;发生故障时要耗费大量的人力物理排查和重新铺设线缆。而在特定场合下…

若依+lodop+jasperreports+ireport 设计打印票据格式(一)

若依lodopjasperreportsireport 设计打印票据格式 一、设计表格 官网下载ireport5.6&#xff0c;解压安装&#xff0c;jdk 1.7适配ireport5.6&#xff0c;jdk1.8不适配 安装好jdk1.7(不用配置path&#xff0c;安装好就行)&#xff0c;进入ireport5.6安装目录&#xff0c;找到…

异步FIFO设计的仿真与综合技术(2)

概述 本文主体翻译自C. E. Cummings and S. Design, “Simulation and Synthesis Techniques for Asynchronous FIFO Design 一文&#xff0c;添加了笔者的个人理解与注释&#xff0c;文中蓝色部分为笔者注或意译。前文链接&#xff1a;异步FIFO设计的仿真与综合技术&#xff0…

模态分析的概念。C++减振器设计。

一、说明 模态分析是工程和物理学中用于研究系统或结构动态特性的技术。它涉及分析系统的振动或振荡的自然模式以及相应的频率、阻尼系数和振型。 在模态分析中&#xff0c;所研究的系统通常表示为一组质量、刚度和阻尼元件&#xff08;在下面的文章中忽略了阻尼&#xff09;。…

ARTS 打卡 第一周,初试ARTS

前言 认识三掌柜的想必都知道&#xff0c;我持续创作技术博客已经有6年时间了&#xff0c;固定每个月发布不少于6篇博文。同时&#xff0c;自己作为一名热爱分享的开发者&#xff0c;像ARTS这样的活动自然少不了我。由于我是打算挤在一起分享&#xff0c;之前都是做了本地文档记…

大数据Flink(七十九):SQL 的容错(Checkpoint)

文章目录 SQL 的容错(Checkpoint) 一、Checkpoint介绍

华为云云耀云服务器L实例评测|云耀云服务器L实例部署SpaceHuggers网页小游戏

华为云云耀云服务器L实例评测&#xff5c;云云耀云服务器L实例部署SpaceHuggers网页小游戏 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点 二、SpaceHuggers小游戏介绍2.1 SpaceHuggers简介2.2 SpaceHuggers游戏玩法 三、实践环境介绍3.1 本次…

在UOS/Deepin下安装 Python 3.11.5 图文详解

01 先把操作系统更新一下 在开始菜单中&#xff0c;找到“终端”&#xff0c;点击启动&#xff0c;并依次输入以下两条命令即可&#xff1a; sudo apt update sudo apt upgrade 特别说明&#xff1a;Uos/Deepin 系统&#xff0c;要先进入“开发者模式”才行。“ 设置 — 通用…

如何用Polygon ID来证明你不是机器人?

1. 引言 喜剧演员约翰穆拉尼在最近的一个单口相声特辑中说&#xff1a;“世界是由机器人管理的&#xff0c;我们一天中的大部分时间都在告诉他们&#xff0c;我们不是一个仅仅登录并查看自己东西的机器人。” 这种经历很常见&#xff0c;从乏味的&#xff08;“找到所有的停车…

软件设计师--考点小总结

成绩展示 在这里插入图片描述 口诀篇 普密网–【图算法,普利姆算法,适合密网,所以与边无光;另外一个图算法就是有关了】 D-AES, 56-128–【DES,AES是对称加密的,而56就是对称加密的算法位数(三重DES,是112,恰好是56倍数),128则是非对称的位数】 排序 快一样,堆占1,…

入行IC| 数字IC设计和验证选哪个好?

很多初入IC行业的新人不知道选择验证还是设计&#xff0c;下面IC修真院就从技能&#xff0c;门槛等方面来为大家分析一下。 数字前端设计工程师是什么&#xff1f; 集成电路设计&#xff08;Integrated Circuit&#xff0c;简称IC&#xff09;一般分为数字IC设计、模拟IC设计…

macOS - 使用VLC

文章目录 关于 VLC安装查看帮助流媒体 MRL 语法:URL 语法:主程序 (core)音频视频截图:窗口属性: 子画面屏幕显示&#xff08;OSD&#xff09;:字幕:覆盖:轨道设置:播放控制:默认设备:高级: 输入播放列表性能选项: 热键跳跃大小: 关于 VLC VLC media player VLC 是一款自由、开…

5个鲜有人知的爬虫技巧

几点鲜有人知的爬虫技巧 技巧一 换个角度&#xff0c;解锁新姿势 在爬取某些 web 网站的时候&#xff0c;被各种反爬弄得哭天喊地。 什么几把 css 字体加密&#xff0c;什么几把 js 的 MD5 等&#xff0c;各种乱七八糟的加密&#xff0c;什么各种飞的验证 这时候&#xff0…

【汇编】计算机系统组成

【汇编】计算机系统组成 文章目录 【汇编】计算机系统组成冯诺依曼结构1. 总线2. 程序存储3. 存储器3.1地址线与字节3.2 读写逻辑 冯诺依曼结构 冯诺伊曼结构&#xff08;Von Neumann Architecture&#xff09;&#xff0c;又称存储程序计算机结构&#xff0c;是计算机体系结构…

VB:二分法查找

VB&#xff1a;二分法查找 二分查找算法 Private Sub Command1_Click()Dim i%, m%, n%Dim x(1 To 10) As SingleFor i 1 To 10x(i) Val(InputBox("请输入"))Next iCall bubbleSort(x)For i LBound(x) To UBound(x) LBound(x)和UBound(x)是用于获取数组x的下界和上…

[移动通讯]【Carrier Aggregation-4】【LTE-3】

前言: 这里面重点讲解一下跟CA 相关的 UL UECapabilityInformation 参考&#xff1a; LTE附着流程详解-UECapabilityInformation_Amao_come_on的博客-CSDN博客 支持载波聚合的终端(UE) 4G | ShareTechnote CSDN CSDN LTE category New_is lte category supported in th…

厂商征集 | 2023年中国RPA市场洞察研究报告正式启动

RPA中国基于在科技行业的资源积累&#xff0c;以及对各领域「技术领导者」、「技术应用者」、「产品服务商」的深度调研&#xff0c;2023年&#xff0c;我们重点推出MI报告 ( Market Insight )、CI Vendor报告&#xff08;Comprehensive Influence Vendor&#xff09;两个系列。…

vvic API接口接入说明:解锁新一代数据可视化的无限可能

随着大数据时代的来临&#xff0c;数据可视化已成为我们理解、分析和呈现复杂数据的重要手段。在这个领域中&#xff0c;vvic以其独特的优势&#xff0c;引领着数据可视化的发展潮流。其强大的API接口&#xff0c;更是为开发者提供了无限可能&#xff0c;让数据可视化变得更为简…