数据结构——单调队列

这篇博客我们来讨论一下单调队列的问题,其实和之前学的单调栈都是一种上通过改变操作来解决问题的一种数据结构

我们先来回忆一下单调栈的内容,这样方便将其和单调队列做区分 

单调栈:(单调性从栈底到栈顶)
1.单调栈是一种栈数据结构,只能在栈顶进行插入和删除操作。
2.单调栈的特点是栈中的元素按照一定的单调性排列,常用的有单调递增和单调递减。
3.在插入新元素时,如果新元素破坏了当前的单调性,则从栈顶删除一部分元素,直到满足单调性    要求。这样可以保证栈中的元素保持单调性。
4.单调栈的典型应用是在寻找下一个更大/更小元素的问题。

单调队列:
1.单调队列是一个双端队列,支持在队列两端进行插入和删除操作。
2.单调队列的特点是队列中的元素按照一定的单调性排列,常用的有单调递增和单调递减。
3.在插入新元素时,如果新元素破坏了当前的单调性,则在队尾删除一部分元素,直到满足     单调性要求。这样可以保证队列中的元素保持单调性。
4.单调队列的典型应用是在滑动窗口中寻找最大/最小值的问题。

总而言之

单调队列和单调栈都是用于维护数据的单调性,但单调队列是双端队列,用于在滑动窗口中寻找最大/最小值,而单调栈是栈数据结构,用于寻找下一个更大/更小元素。 

单调队列的运行过程

分析一下如何去寻找到一个窗口中的最大/最小值

[2,7,6,5,4,8,1],假设我们的窗口大小为3,我们考虑在窗口滑动过程中,每个窗口的最大值为多少

我们的下标从1开始,当我们的下标在3之前时,我们的窗口还未形成

[2),7,6,5,4,8,1]

[2,7),6,5,4,8,1]

当下标从3开始后,我们的窗口正式形成

[(2,7,6),5,4,8,1]很明显窗口最大值为7

当我们在往后滑动的时候逐步寻找最大值

[2,(7,6,5),4,8,1],最大值为7

[2,7,(6,5,4),8,1],最大值为6

[2,7,6,(5,4,8),1],最大值为8

[2,7,6,5,(4,8,1)],最大值为8

我们用数据结构的想法来分析一下,如何才能取到那些最大值呢?(队列头部就是最大值)

假设我们有一个队列

我们在下标为1的时候将2存进去

下标为2的时候,我们在存7的时候发现2比7小,因此直接将2从队尾弹出,将7放进去

后续下标3,4,5都是直接放就行,但是当5下标的数放进去之后,7将从队头直接滑出,因为滑动窗口的大小为3,因此应当从队头滑出

后续和上面操作差不多

例题

滑动窗口的最大值

思路:滑动窗口板题,用一个双端队列去统计这个窗口的最大值即可

class Solution {  
public:  
    vector<int> maxInWindows(vector<int>& nums, int k) {  
        int n = nums.size();  
        vector<int> result;   
        deque<pair<int, int>> que;  

        for (int i = 0; i < n; i++) {  
            while (!que.empty() && que.front().second <= i - k) {  
                que.pop_front();  
            }  

            while (!que.empty() && que.back().first < nums[i]) {  
                que.pop_back();  
            }  

            que.push_back({nums[i], i});  

            if (i >= k - 1) {  
                result.push_back(que.front().first);  
            }  
        }  

        return result;  
    }  
}; 

 P1886 滑动窗口 /【模板】单调队列

也是板题,就是再多统计一遍最小值即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k;
struct node{
	int x;
	int pos;
}a[1000005];
deque<node> que;
int f_max[1000005];
int f_min[1000005];
signed main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].x;
		a[i].pos=i;
	} 
	for(int i=1;i<=n;i++)
	{
		while(!que.empty()&&que.back().x<a[i].x)
		{
			que.pop_back();
		}
		que.push_back(a[i]);
		if(que.front().pos<i-k+1)
		{
			que.pop_front();
		}
		if(i>=k)
		{
			f_max[i]=que.front().x;
		}
	}
	while(!que.empty())
	{
		que.pop_back();
	}
	for(int i=1;i<=n;i++)
	{
		while(!que.empty()&&que.back().x>a[i].x)
		{
			que.pop_back();
		}
		que.push_back(a[i]);
		if(que.front().pos<i-k+1)
		{
			que.pop_front();
		}
		if(i>=k)
		{
			f_min[i]=que.front().x;
		}
	}
	for(int i=k;i<=n;i++)
	{
		cout<<f_min[i]<<" ";
	}
	cout<<"\n";
	for(int i=k;i<=n;i++)
	{
		cout<<f_max[i]<<" ";
	}
	return 0;
}

 绝对差不超过限制的最长连续子数组

 思路:题目说要求一个区间内(也就是一个窗口内)的最大值和最小值的差值小于limit的最长序列,我们可用两个队列去存储,一个存储最大值一个存储最小值,然后用两个指针L和R去看当前的区间大小为多少吗,如果当前最大值和最小值的区间小于限制,可以直接统计长度,否则就要去弹出前面的元素,让L指针向后滑动,然后直到有一个队列为空,或者最大值和最小值的差值小于limit为止

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        struct node{
            int x;
            int pos;
        }a[100005];
        int n=nums.size();
        for(int i=1;i<=n;i++)
        {
            a[i].x=nums[i-1];
            a[i].pos=i;
        }
        deque<node> que_min;
        deque<node> que_max;
        int l=1;
        int ans=0;
        for(int r=1;r<=n;r++)
        {
            while(!que_max.empty()&&que_max.back().x<=a[r].x)
            {
                que_max.pop_back();
            }
            while(!que_min.empty()&&que_min.back().x>=a[r].x)
            {
                que_min.pop_back();
            }
            que_max.push_back(a[r]);
            que_min.push_back(a[r]);
            while(que_max.front().x-que_min.front().x>limit&&!que_max.empty()&&!que_min.empty())
            {
                if(que_max.front().pos==l)
                {
                    que_max.pop_front();
                }
                if(que_min.front().pos==l)
                {
                    que_min.pop_front();
                }
                l++;
            }
            ans=max(ans,r-l+1);
        }
        return ans;
    }
};

P2698 [USACO12MAR] Flowerpot S

这题其实也一样,只不过他是给你雨滴的横坐标和纵坐标,当我们的最长下落时间和最短下落时间要差d,也就是说明纵坐标的高度要差d

首先,我们应当将雨滴按照x进行排序,让小的在前面,用两个队列去统计区间内的最大值和最小值,然后直到区间内的最大值和最小值的差值大于d时候再去统计区间内的长度,然后滑动左指针,逐渐改变范围

但是有可能左指针划到右指针的右边,所以在算值的时候要用绝对值

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,d;
int x,y;
struct node{
	int x;
	int y;
	int pos;
}a[100005];
bool cmp(node a,node b)
{
	return a.x<b.x;
}
signed main()
{
	cin>>n>>d;
	int maxn=0;
	int minn=0x3f3f3f3f;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].x>>a[i].y;
		maxn=max(maxn,a[i].y);
		minn=min(minn,a[i].y);
	}
	if(maxn-minn<d)
	{
		cout<<"-1\n";
		return 0;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++)
	{
		a[i].pos=i;
	}
	deque<node> que_max;
	deque<node> que_min;
	int ans=0x3f3f3f3f;
	int l=1;
	for(int i=1;i<=n;i++)
	{
		while(!que_max.empty()&&que_max.back().y<=a[i].y)
		{
			que_max.pop_back();
		}
		while(!que_min.empty()&&que_min.back().y>=a[i].y)
		{
			que_min.pop_back();
		}
		que_max.push_back(a[i]);
		que_min.push_back(a[i]);
		while(!que_max.empty()&&!que_min.empty()&&que_max.front().y-que_min.front().y>=d)
		{
			ans=min(ans,abs(que_max.front().x-que_min.front().x));
			if(que_max.front().pos==l)
			{
				que_max.pop_front();
			}
			if(que_min.front().pos==l)
			{
				que_min.pop_front();
			}
			l++;
		}
	}
	cout<<ans;
	return  0;
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决 Maven 部署中的 Artifact 覆盖问题:实战经验分享20241204

&#x1f6e0;️ 解决 Maven 部署中的 Artifact 覆盖问题&#xff1a;实战经验分享 &#x1f4cc; 引言 在软件开发过程中&#xff0c;持续集成和持续部署&#xff08;CI/CD&#xff09;是提高开发效率和代码质量的关键手段。Hudson 和 Maven 是两种广泛使用的工具&#xff0…

[go-redis]客户端的创建与配置说明

创建redis client 使用go-redis库进行创建redis客户端比较简单&#xff0c;只需要调用redis.NewClient接口创建一个客户端 redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379",Password: "",DB: 0, })NewClient接口只接收一个参数red…

Solving the Makefile Missing Separator Stop Error in VSCode

1. 打开 Makefile 并转换缩进 步骤 1: 在 VSCode 中打开 Makefile 打开 VSCode。使用文件浏览器或 Ctrl O&#xff08;在 Mac 上是 Cmd O&#xff09;打开你的 Makefile。 步骤 2: 打开命令面板 按 Ctrl Shift P&#xff08;在 Mac 上是 Cmd Shift P&#xff09;&…

交换机四大镜像(端口镜像、流镜像、VLAN镜像、MAC镜像)应用场景、配置实例及区别对比

在网络管理中&#xff0c;端口镜像、流镜像、VLAN镜像和MAC镜像都是用于监控和分析网络流量的重要技术。 端口镜像&#xff08;Port Mirroring&#xff09; 定义&#xff1a;端口镜像是将一个或多个源端口的流量复制到一个目标端口&#xff0c;以便于网络管理员能够监控和分析…

Unity数据持久化

二进制数据持久化的好处&#xff1a;安全、效率高、利于网络通信 文章目录 补充文件夹相关EditorResourcesSteammingAsset 序列化和反序列化序列化反序列化 二进制数据持久化转换为字节数据文件操作写入字节&#xff1a;读取字节安全关闭文件夹操作操作文件夹目录信息和文件信息…

【机器学习】机器学习的基本分类-监督学习-随机森林(Random Forest)

随机森林是一种基于集成学习&#xff08;Ensemble Learning&#xff09;思想的算法&#xff0c;由多个决策树构成。它通过结合多棵决策树的预测结果来提升模型的泛化能力和准确性&#xff0c;同时减少过拟合的风险。 1. 随机森林的核心思想 多样性&#xff1a; 随机森林通过引…

中国矿业大学《2024年868自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《中国矿业大学868自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2024年真题 Part1&#xff1a;2024年完整版真题 2024年真题

SQL SERVER 2016 AlwaysOn 无域集群+负载均衡搭建与简测

之前和很多群友聊天发现对2016的无域和负载均衡满心期待&#xff0c;毕竟可以简单搭建而且可以不适用第三方负载均衡器&#xff0c;SQL自己可以负载了。windows2016已经可以下载使用了&#xff0c;那么这回终于可以揭开令人憧憬向往的AlwaysOn2016 负载均衡集群的神秘面纱了。 …

生产看板到底在看什么?

说起生产看板&#xff0c;可能很多人脑海里冒出来的画面是&#xff1a;车间里一块挂在墙上的大板子&#xff0c;上面贴满了各式各样的卡片、表格&#xff0c;甚至还有几个闪闪发光的指示灯。但是&#xff0c;无论是精益生产方式代表——丰田&#xff0c;还是当下以“智能制造”…

数据链路层(四)---PPP协议的工作状态

1 PPP链路的初始化 通过前面几章的学习&#xff0c;我们学了了PPP协议帧的格式以及组成&#xff0c;那么对于使用PPP协议的链路是怎么初始化的呢&#xff1f; 当用户拨号上网接入到ISP后&#xff0c;就建立起了一条个人用户到ISP的物理链路。这时&#xff0c;用户向ISP发送一…

第四届全国过程模拟与仿真大会召开,积鼎科技相伴大会6年成长

第四届全国过程模拟与仿真学术会议于2024年11月29日-12月2日在广州圆满召开。积鼎科技&#xff0c;作为自主流体仿真软件研发的领航企业&#xff0c;与大会相伴四年&#xff0c;自首届以来一直积极参与其中&#xff0c;见证了大会从初创到逐渐壮大的全过程。每一次参会&#xf…

【RDMA】RDMA read和write编程实例(verbs API)

WRITE|READ编程&#xff08;RDMA read and write with IB verbs&#xff09; &#xff08;本文讲解的示例代码在&#xff1a;RDMA read and write with IB verbs | The Geek in the Corner&#xff09; 将 RDMA 与verbs一起使用非常简单&#xff1a;首先注册内存块&#xff0c…

JAVAWeb之CSS学习

前引 CSS&#xff0c;层叠样式表&#xff08;Cascading Style Sheets&#xff09;&#xff0c;能够对网页中元素位置的排版进行像素级精确控制&#xff0c;支持几乎所有的字体字号样式&#xff0c;拥有网页对象和模型样式编辑的能力&#xff0c;简单来说&#xff0c;美化页面。…

Linux CentOS

​阿里云开源镜像下载链接 https://mirrors.aliyun.com/centos/7/isos/x86_64/ VMware 安装 CentOS7 自定义 下一步 选择稍后安装操作系统 选择 输入 查看物理机CPU内核数量 CtrlShiftEsc 总数不超过物理机内核数量 推荐内存 自选 推荐 推荐 默认 拆分成多个 默认 自定义硬件…

gazebo 仿真阶段性问题汇总三

目录 报错&#xff1a;关节设置为 revolute 缺少 limit 属性解决方法 轮子转向左右相反解决方法 rviz2只显示一次雷达数据&#xff0c;刷新后消失解决方法 修改2D雷达为3D雷达2d 雷达3D 雷达 报错&#xff1a;关节设置为 revolute 缺少 limit 属性 revolute 表示是有限制的旋转…

python学习笔记14 python中的库,常见的内置库(random、hashlib、json、时间、os)

接着上一篇python学习记录的内容&#xff0c;今天我们来看库 内置库&#xff1a;time、random、os、json…第三方库&#xff1a;requests,pandas,numpy…自定义库&#xff1a;xxx.py 导入的方式 import 直接将一个库导入进来 import base.day04.login_demo as t # 导入login_…

微信小程序版小米商城的搭建流程详解!

很多初学微信小程序语法的同学&#xff0c;可能不知道如何布局和搭建一个项目&#xff0c;下面我将讲解初学者如何搭建项目和注意事项。 一、 app.json的配置 {"pages": ["pages/index/index","pages/classification/classification","pag…

PETR:Position Embedding Transformation forMulti-View 3D Object Detection

全文摘要 本文介绍了一种名为“位置嵌入变换&#xff08;PETR&#xff09;”的新方法&#xff0c;用于多视角三维物体检测。该方法将三维坐标的位置信息编码为图像特征&#xff0c;并产生具有三维位置感知能力的特征。通过对象查询可以感知这些特征并进行端到端的目标检测。在…

2024前端框架年度总结报告(二):新生qwik+solid和次新生svelte+Astro对比 -各自盯着前端的哪些个痛点 - 前端的区域发展差异

引言 2024年&#xff0c;前端开发依然是技术领域的热点之一。随着 Web 应用的日益复杂&#xff0c;前端框架的更新换代也加速了。尽管 React、Vue 和 Angular 老牌框架年度总结 等“老牌”框架仍然占据着主流市场&#xff0c;但一些新兴的框架在不断挑战这些“巨头”的地位&am…

多模态大语言模型的对比

简介 文章主要对比了包括 VideoLLaMA 2 、CogVLM2-video 、MiniCPM-V等模型 目前主流的多模态视觉问答大模型&#xff0c;大部分采用视觉编码器、大语言模型、图像到文本特征的投影模块 目录 简介1. VideoLLaMA 21.1 网络结构1.2 STC connector具体的架构 2. MiniCPM-V 2.62.…