首页 > 其他分享 >[刷题笔记] 关于栈 & 队列常用操作方法的再探索

[刷题笔记] 关于栈 & 队列常用操作方法的再探索

时间:2024-01-28 21:58:14浏览次数:30  
标签:出栈 括号 队列 操作方法 cin int include 刷题

Part 0:序

其实本来这都是很基础的东西,可惜野路子出身基础并不扎实。

借着这个机会整合一下吧。也做了一些题了解了一些基本操作方法。

本文对于 栈 和 队列的原理不再过多赘述,默认读者掌握基本原理。

参考题单:
数据结构加强001:栈和队列

2024现代信息学测试1:栈和队列

本文所讲例题来源以上题单。

【团队内部题单】

所谓 “栈” 就是一种先进后出的数据结构,最典型的,可以用来进行运算顺序的处理。我们只需要在计算乘法的时候将 stack 顶弹出和当前数据乘法运算后再入栈即可。

典例:P1981 表达式求值

上述是栈的基本操作。接下来会给出几个例题来进一步强化栈的操作。

典例1:P4387 验证栈序列

Problem

Description

给定入栈序列 \(s\),和一个序列 \(k\),你需要判断在入栈顺序为 \(s\) 的前提下,出栈顺序是否可能为 \(k\)。

Analysis
Analysis

注意到我们需要判断出栈序列是否合法,显然我们可以直接递归搜索每一种可能的出栈顺序,然后比对即可。本题没有给定数据范围,但是会 TLE。

考虑“贪心地”去尽可能满足它所给定的出栈序列。

具体地,每次入栈后,如果此时的栈顶元素是当前应当出栈的(也就是给定出栈序列),则出栈。需要注意每次入栈后可以连续出栈,所以我们需要 while 循环,而不是默认只能出一个元素。

如此操作,我们确保了每次出栈操作是合法的。最后判断栈是否为空即可。

对于本题,我们所有的操作都可以在 main 函数里解决,所以 stack 开局部变量即可。避免忘记多测清空。

本题的本质就是模拟栈操作。

Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
using namespace std;
const int N = 100010;
int a[N],b[N];
int q;
stack <int> s;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>q;
	while(q--)
	{
		int cnt = 1;
		int n;
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<=n;i++) cin>>b[i];
		for(int i=1;i<=n;i++)
		{
			s.push(a[i]);
			while(!s.empty() && s.top() == b[cnt])
			{
				s.pop();
				cnt++;
			}
		}
		if(s.empty()) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
		while(!s.empty()) s.pop();
	}
	return 0;
}

典例2:P3056

Description

Problem

给出一个偶数长度的括号序列,问最少修改多少个括号可以使其平衡。

Analysis
Analysis

首先明确,本题是 修改括号而不是括号配对! 题意需要明确。

然后如何处理?我们不妨先将配对的括号全部配对,这很简单,使用 stack 即可完成。

接下来我们会剩下些许左括号和右括号,分别记为 \(s_1,s_2\)。

接下来考虑如何将这些 无法配对 的括号通过一系列修改使其配对。

考虑手动构造几组样例,如下:

image

(图1)
image
(图2)

通过构造样例,不难发现 对于无法配对的括号,只有可能是一连串的左括号和一连串的右括号,不可能出现形似 ”()“的,原因显然。

考虑对于这样的括号如何配对。

发现对于图1,左括号和右括号都是 偶数个,贪心地考虑,我们可以将左括号和右括号间隔排列,也就是需要更改 \(s_1\div 2 + s_2\div 2\) 个括号。

对于图2,像图1一样构造后一定会剩下一个 ")(",这样我们只能通过添加括号来配对,只需要在 \(s_1\div 2 + s_2\div 2\) 的基础上 \(+2\) 即可。由于 C++ 默认向 0 取整,对于正数也就是向下取整,所以无需特殊处理。

至此,本题的解。考虑到最后发现本题是个人类智慧贪心构造题!只不过在贪心前一定要处理好配对好的括号。

Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
using namespace std;
stack <int> s;
int num = 0;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    char ch;
    int cnt = 0;
    while(cin>>ch)
    {
        if(ch == '(') s.push(++cnt);
        else
        {
            if(!s.empty()) s.pop();
            else num ++;
        }
    }
    if(num % 2 == 0 && s.size() % 2 == 0) cout<<num/2+s.size()/2<<endl;
    else cout<<num/2+s.size()/2+2<<endl;
    return 0;
}

典例3:P2866

Description

image

Analysis

本题是单调栈的模板题,参见:SXqwq 的单调栈学习笔记

队列

所谓 "队列" 是一种先进先出的数据结构。具体地,队列一端进,一端出。

诚然,这只是最基础地队列,队列只是一种模型,大家千万不要被束缚。下面列举了几个基础应用。

STL 板子

P2952

Analysis

没啥好分析的,队列的两端都可以进出,直接 deque 即可。

Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <deque>
using namespace std;
int n;
int cow_cnt = 1;
deque <int> q;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        char ctl;
        cin>>ctl;
        if(ctl == 'A')
        {
            char ctl2;
            cin>>ctl2;
            if(ctl2 == 'L') q.push_front(cow_cnt++);
            else q.push_back(cow_cnt++);
        }
        else if(ctl == 'D')
        {
            char ctl2;
            int k;
            cin>>ctl2;
            if(ctl2 == 'L')
            {
                cin>>k;
                while(k--)
                {
                    q.pop_front();
                }
            }
            else 
            {
                cin>>k;
                while(k--)
                {
                    q.pop_back();
                }
            }
        }
    }
    while(!q.empty())
    {
        cout<<q.front()<<endl;
        q.pop_front();
    }
    return 0;
}

典例2:P3662

P3662

Description

共有N个信号灯,编号为1~N,有B个信号灯损坏,给你它们的编号。

问,最少修好几个信号灯,可以有K个编号连续的信号灯。

Analysis

Analysis

记每个需要修理的路灯为 \(1\) ,其他为 \(0\)。

题目要求 最少修好多少个灯,可以有 \(K\) 个编号连续的信号灯

不妨首先算 \(1-k\) 号路灯有几个需要修的,然后滑块移动即可。

当然也有用前缀和处理的,我当时没想到ww

Code
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N  = 100010;
const int INF = 0x3f3f3f3f;
int n,k,b;
int num[N];
int sum;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>k>>b;
	for(int i=1;i<=b;i++)
	{
		int p;
		cin>>p;
		num[p] ++;
	}
	for(int i=0;i<=k;i++) sum += num[i];
	int l = 0,r = k;
	int minn = INF;
    minn = min(minn,sum);
	while( r <= n)
	{
     //   cout<<l<<" "<<r<<endl;
     l ++;
		r ++;
        minn = min(minn,sum);
		sum -= num[l];
		sum += num[r];
		minn = min(minn,sum);
	}
	cout<<minn<<endl;
	return 0;
}

标签:出栈,括号,队列,操作方法,cin,int,include,刷题
From: https://www.cnblogs.com/SXqwq/p/17986073

相关文章

  • 数据结构——顺序队列(循环)
    采用顺序表的方式实现循环队列。其中关键在于如何判断队列已满。通常情况下,当对头和队尾指向同一个节点时,可以判断为队空。但是,倘若队尾不断增加,最后队尾也会指向对头,此时队满和队空的判断条件一致。以下有三种对于对于队满判断的方法。1、舍弃顺序表中的一个元素,也就是说,当队尾......
  • 单调队列
    单调队列其实是一个双端队列,可以从队首和队尾出队,但是只能在队尾入队。队列中的元素关系具有单调性。对于维护好的单调队列,队内元素是有序的,取出最大最小值的复杂度是\(O(1)\),每个元素各进队列一次,出队一次,因此复杂度是\(O(n)\)。单调队列是主要解决滑动窗口类问题的数据结构。......
  • [office] Excel中Count函数统计考勤[经验] 金领冠奶粉怎么辨别真伪表的操作方法
    Excel越来越广泛的被使用,从日常的记录到工作中的操作,如果利用它进行考勤能够大大提高效率,而这个过程只需要借助COUNT函数。今天,小编就教大家在Excel中Count函数统计考勤表的操作方法。Excel中Count函数统计考勤表的操作步骤如下:1、COUNT函数是用于计算参数列表中的数字......
  • [office] Excel中有效数据统计个数的操作方法
    Excel数据表格中,某一列的数据并不是每一行的有数值,而是没有数据的直接放空,或填写无的字样。这样想统计这一列中有效数据的个数,就需要用到Excel的函数,今天,小编就教大家在Excel中有效数据统计个数的操作方法。Excel中有效数据统计个数的操作步骤如下:打开待统计的数据表格......
  • priority_queue简介与用法(优先队列)
    priority_queue简介与用法 一、简介 1.概念priority_queue是C++标准库中的一个容器适配器(containeradapter),用于实现优先队列(priorityqueue)的数据结构。优先队列是一种特殊的队列,其中的元素按照一定的优先级进行排序,每次取出的元素都是优先级最高的。它的底层实现通常使......
  • Leetcode刷题第四天-双指针-二分法
    15:三个数之和链接:15.三数之和-力扣(LeetCode)em...双冲for循环,从头去遍历,0-(a+b)是否在列表中,最终timeout数组从小到大排序,设置三个指针,i从头遍历到lens-1,j从i+1开始,k从lens-1开始,sums==0,放入结果,大于0,k-1,小于0,j+1如果i和i+1比较,相同跳过的话,会丢结果,i和i-1相等跳过,因为i-1已......
  • nodejs消费rabbitmq队列消息
    index.jsvaramqp=require('amqplib/callback_api');constMyConsume=require('./MyConsume');amqp.connect('amqp://name:password!@localhost:5672/vhost',function(error0,connection){if(error0){throwerror......
  • 线性表 - 栈和队列
    栈后进先出LIFO两种实现方式使用数组实现的叫静态栈使用链表实现的叫动态栈相关题目简单难度225.用队列实现栈https://leetcode.cn/problems/implement-stack-using-queues/classMyStack{  privateQueue<Integer>q1;  privateQueue<Integer>q2; ......
  • 【数据结构】72变的双端队列
    双端队列前言大家好,很高兴又和大家见面啦!!!在前面的篇章中,咱们详细介绍了队列这种新的数据结构,现在我们简单的回顾一下队列的三要素——数据的逻辑结构、数据的存储结构以及数据的运算。数据的逻辑结构队列的数据元素在逻辑上是呈现线性结构,也就是说队列也是一种线性表,只不过是一种......
  • 进程间通信(队列和生产消费模型)
    (一)引入(1)什么是进程间的通信IPC进程间通信(Inter-ProcessCommunication,IPC)是指两个或多个进程之间进行信息交换的过程它是一种计算机编程技术,用于在不同的进程之间共享数据和资源(2)如何实现进程间通信借助于消息队列,进程可以将消息放入队列中,然后由另一个进程从队列中取......