【题目/算法训练】:单调队列单调栈

🚀 前言:

【算法】单调队列&&单调栈 可以在看完这篇文章后,再来写下面的题目

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

思路:

      1) 就相当于滑动窗口,维护滑动窗口内的两个值,一个是最大值,一个是最小值,如果当前滑动窗口的最大值和最小值的差值都不超过  limit ,说明滑动窗口内任意两个数的差值都不会超过  limit 

       2)由于需要维护两个值 ,因此我们需要两个单调队列,同时维护一个区间的值,一个去维护最大值,一个去维护最小值

       3) 由于要求最长连续子数组的长度,那么我们假设已经 有【l,r - 1】满足条件的最长子数组长度,然后尾指针向后移动一位,假设此时【l,r】的最大差值已经超过 limit,此时 应该向后移动,,这道题本质就是一个变长的滑动窗口,其长度是根据题目所给条件来进行调整。

class Solution {
public:int longestSubarray(vector<int>& nums, int limit) {//处理边界情况if (limit < 0) return 0;deque<int> min_q, max_q;int l = 0, ans = 1 ;min_q.push_back(0);max_q.push_back(0);for (int r = 1, n = nums.size(); r < n; r++) {while (!min_q.empty() && nums[r] < nums[min_q.back()]) min_q.pop_back();while (!max_q.empty() && nums[r] > nums[max_q.back()]) max_q.pop_back();min_q.push_back(r);max_q.push_back(r);if (nums[max_q.front()] - nums[min_q.front()] > limit) {if (min_q.front() == l) min_q.pop_front();if (max_q.front() == l) max_q.pop_front();l++;}ans = max(ans, r - l + 1);}return ans;}
};

二、最大矩形面积

思路:

 1) 假设我们现在可以切割出的最大矩形面积为S;

 2)此时矩形高度等于其范围内最矮木板的高度。

 3)假设最大矩形两边各有1号和2号两块木板,此时1和2号的高度比矩形高度要小,

 4) 以每一块木板作为矩形最大高度的基准值,然后枚举去判断能够可以切出来的最大面积。因此我们需要求该木板左右两边最近的1,2号木板,就可以用单调栈。

#include<iostream>
#include <vector>
#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
using namespace std;typedef long long ll;int main()
{int n;cin >> n;vector<ll> arr(n + 2, -1);  //让最左边和最右边木板旁边还有木板vector<ll> l(n + 2), r(n + 2);//分别存储左右两边小于第i块木板的那个下标for (int i = 1; i <= n; i++) cin >> arr[i];stack<ll>s;for (int i = 1; i <= n + 1; i++) {while (!s.empty() && arr[i] < arr[s.top()]) {r[s.top()] = i;s.pop();}s.push(i);}while (!s.empty()) s.pop();for (int i = n; i >= 0; i--) {while (!s.empty() && arr[i] < arr[s.top()]) {l[s.top()] = i;s.pop();}s.push(i);}ll ans = 0;for (int i = 1; i <= n; i++) { //以每一块木板为基准值切出的最大面积ll height = arr[i], width = r[i] - l[i] - 1;ans = max(ans, height * width);}cout << ans << "\n";return 0;
}

三、接雨水

首先由题目可知只有凹形才能接雨水,因此我们假设已经存在1号柱子到2号柱子如下构成的绿色接雨水面积,当再来了一个3号柱子,我们又可以新接一些雨水,即黄色面积,假设1号柱子的下标为i,3号柱子的下标为j,此时黄色部分的长度为 j - i,高度为min (h3 - h1) -h2

因此我们不断往后增加柱子,比如4号柱子,那里又可以增加红色雨水面积,加入5号柱子,计算不出我们可以接雨水的面积,再增加6号(仍然没有新增雨水的量),再加入7号柱子,

此时h7和h5可以算出可以接雨水的量,此时可以当作h6不存在,如下图所示

因此可知我们应该需要维护的就是上图中h4、h5、h7这种单调递减的序列,然后每次在后面增加一个柱子,如果我们增加的柱子比我们最后的柱子要高,就可以形成新的雨水,然后计算增加雨水的量,进行累加即可,易知应该需要用到单调栈

class Solution {
public:int trap(vector<int>& height) {stack<int> s;int ans = 0;for (int i = 0; i < height.size(); i++) {while (!s.empty() && height[s.top()] < height[i]){int min_h = height[s.top()];//记录弹出柱子的高度s.pop();if (s.empty()) break;//计算出弹出柱子两侧相邻最矮柱子的高度与弹出柱子高度差,再乘以下标差,此时就为新增雨水面积ans = ans + (min(height[s.top()], height[i]) - min_h) * (i - s.top() - 1); }s.push(i);}return ans;}
};

四、和至少为K的最短子数组

思路:

       假设如下每个节点都代表了前缀和数组中的每一个值,假设当前已经遍历到黄色这个节点,绿色代表黄色点之前所有点的最小值,红色点代表从绿色到黄色点区间内的最小值,蓝色点则代表红色点到黄色点区间内的最小值

       此时我们需要找到黄色点前的一个点,使得黄色点需要减去那一个值,并且这个差值必须大于等于K,因此我们需要找的就是黄色点前的最小值,假如黄色点减去绿色点的差值大于等于K,但是由于我们要求最短子数组,此时绿色点就可以被抛弃,即弹出,因此我们就需要在绿色点后面找点,即红色点,如果黄色点与红色点的差值也大于等于K,那么黄色点也弹出,那我们就去找蓝色点,不断往后,即需要维护绿红蓝这三个点

        易知应该使用单调队列来解决该题,即把原数组处理为前缀和数组,然后将原数组中每一项依次性压入到单调队列中,每次压入前,需要用当前的值和单调队列的队首进行比较,若当前值减去队首元素的值大于等于K,此时队首元素就可以出队,然后再把当前元素压入单调队列

class Solution {
public:int shortestSubarray(vector<int>& nums, int k) {int n = nums.size();vector<long long> s(n + 1, 0);//前缀和数组for (int i = 1; i <= n; i++) {s[i] = s[i - 1] + nums[i - 1];}deque<int>q;q.push_back(0);int ans = n + 1;for (int i = 1; i <= n; i++) {while (!q.empty() && s[i] - s[q.front()] >= k) {ans = min(ans, i - q.front());q.pop_front();}while (!q.empty() && s[i] < s[q.back()]) q.pop_back();q.push_back(i);}if (ans == n + 1) return -1;return ans;}
};

五、双生序列

思路:

       假设已有A、B两序列,两个都固定了结尾位置r的情况下,它们的趋势相同就是从最小值到最小值后面的最小值到最小值后面的最小值的最小值的所在位置相同,然后将黄蓝绿红的位置存储在单调队列中,其趋势相同也意味着它们在单调队列所存储的元素也相同,注意在单调队列中所存储位置对应值应该是单调递增的

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <deque>
using namespace std;int main()
{int n;cin >> n;vector<int> a(n + 1), b(n + 1);for (int i = 1; i <= n; i++) cin >> a[i];for (int i = 1; i <= n; i++) cin >> b[i];deque<int> ap, bp;int p; //找最大值ifor (p = 1; p <= n; p++){while (!ap.empty() && a[p] <= ap.back()) ap.pop_back();while (!bp.empty() && b[p] <= bp.back()) bp.pop_back();ap.push_back(a[p]);bp.push_back(b[p]);if (ap.size() != bp.size()) break; //说明到此位置结束}cout << p - 1<< endl; return 0;
}

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

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

相关文章

Linux常用选项和指令

目录 Linux指令使用注意 用户创建与删除 ls指令 ls指令介绍 ls常见选项 ls选项组合使用 pwd指令 Linux文件系统结构 多叉树结构文件系统介绍 多叉树结构文件系统的特点 cd指令 绝对路径 相对路径 cd指令介绍 家户目录 最近访问的目录 touch指令 ​编辑mkdir指…

3D模型格式转换工具HOOPS Exchange如何访问产品制造信息(PMI)?

在当今的制造和设计领域&#xff0c;产品制造信息&#xff08;PMI&#xff09;在确保零件和产品满足精确规格方面发挥着至关重要的作用。PMI&#xff0c;特别是几何尺寸和公差&#xff08;GD&T&#xff09;&#xff0c;提供了制造过程中必须遵循的详细指导。 随着技术的进…

js ES6 part2

forEach遍历 forEach() 方法用于调用数组的每个元素&#xff0c;并将元素传递给回调函数 主要使用场景&#xff1a; 遍历数组的每个元素 语法 被遍历的数组.forEach(function(当前数组元素&#xff0c;当前元素索引号){ //函数体 }) 1. forEach 主要是遍历数组 2. 参数当前…

Milvus核心组件(1)- Architecture

目录 cluster 模式 数据请求处理流程 总流程 逻辑channel 到物理channel 数据维护流程 cluster 模式 上一篇其实已经说过 standalone 模式&#xff0c;其实集群模式大同小异&#xff0c;只是在不同机子间使用Kafka或者其他消息中间件保证数据及逻辑的一致性。 Log Broker…

Mac 上安转文字转 SQL 利器 WrenAI

WrenAI 是一个开源的 Text-SQL 的工具&#xff0c;通过导入数据库结构&#xff0c;通过提问的方式生成 SQL。本文将讲述如何在 MacOS 上安装 WrenAI。要运行WrenAI&#xff0c;首先需要安装 Docker 桌面版。 下载 WrenAI https://github.com/Canner/WrenAI/releases/tag/0.7.…

java数组之线性查找、二分法查找

一、线性查找 思想&#xff1a;如果想在一个数组中查找是否有某个元素&#xff0c;最容易想到的办法就是遍历数组&#xff0c;将数组中元素与想要查找的元素逐个对比&#xff0c;如果相等表示找到了&#xff0c;如果不等&#xff0c;则表示没找到。这就是线性查找的思想。 案例…

算法导论 总结索引 | 第四部分 第十七章:摊还分析

1、数据结构的一个操作序列中 所执行的 所有操作的平均时间&#xff0c;来评估该操作的代价。摊还分析 不同于平均情况分析&#xff0c;它并不涉及概率&#xff0c;它可以保证最坏情况下每个操作的平均性能 它是一种平均情况下的 性能分析方法&#xff0c;用于 评估一系列操作的…

开源流程表单设计器都有哪些值得一提的优势?

如果需要提质、增效、降本&#xff0c;不妨来了解下低代码技术平台、开源流程表单设计器的功能和优势特点。想要实现流程化办公&#xff0c;低代码技术平台是助力增效的理想工具。功能灵活、操作方便、好维修、可视化操作等优势都是其深受行业喜爱的优势特点。通过本文&#xf…

Errno2:No such file or directory,在当前文件确实没有该图片,怎么解决?

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

常用网络概念

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ​​ 目录 了解组织 局域网技术 …

高深宽比刻蚀和纳米级图形化推进存储器的路线图

随着市场需求推动存储器技术向更高密度、更优性能、新材料、3D堆栈、高深宽比 &#xff08;HAR&#xff09; 刻蚀和极紫外 &#xff08;EUV&#xff09; 光刻发展&#xff0c;泛林集团正在探索未来三到五年生产可能面临的挑战&#xff0c;以经济的成本为晶圆厂提供解决方案。 …

【进阶篇-Day7:JAVA中Date、LocalDate等时间API的介绍】

目录 1、概述2、JDK8(-) 时间类2.1 Date类&#xff1a;&#xff08;1&#xff09;构造方法&#xff1a;&#xff08;2&#xff09;常用成员方法&#xff1a; 2.2 SimpleDateFormat类&#xff1a;2.3 总结&#xff1a;2.4 Calendar类介绍&#xff1a; 3、JDK8() 时间类3.1 日历类…

fortran简单排序算法,对一维、二维矩阵进行正序或倒序排序

fortran简单排序算法&#xff0c;对一维、二维矩阵进行正序或倒序排序 0. 引言1. 算法实现1.1 一维数组排序1.2 二维数组排序1.2 module文件 2. 结语 0. 引言 排序算法是计算机科学中的一项重要技术&#xff0c;它将一组数据按照特定的顺序排列起来。排序算法有很多种&#xff…

设计模式探索:责任链模式

1. 什么是责任链模式 责任链模式 (Chain of Responsibility Pattern) 是一种行为型设计模式。定义如下&#xff1a; 避免将一个请求的发送者与接收者耦合在一起&#xff0c;让多个对象都有机会处理请求。将接收请求的对象连接成一条链&#xff0c;并且沿着这条链传递请求&…

【C++深度学习】多态(概念虚函数抽象类)

✨ 疏影横斜水清浅&#xff0c;暗香浮动月黄昏 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &…

appium环境准备

前言: 本系列教程会从软件的基本安装开始,最终目的是通过完成几个案例后, 大家实现自由抓取App中想要的资源。 本系列以后会更的: Appium基本使用及控制真机及安卓模拟器Mitmproxy抓包工具的基本使用Fiddler抓包软件的基本使用 了解了以上的基本操作,我们就可进行手机资源…

Splunk Enterprise路径遍历漏洞风险通告

今日&#xff0c;亚信安全CERT监控到安全社区研究人员发布安全通告&#xff0c;披露了Splunk Enterprise 路径遍历漏洞(CVE-2024-36991)。该漏洞发生在9.2.0<version<9.2.2&#xff0c;9.1.0<version<9.1.5&#xff0c;以及9.0.0<version<9.0.10的windows版本…

3102.力扣每日一题7/9 Java(TreeMap)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;算法练习关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 目录 TreeMap详解 解题思路 解题方法 时间复杂度 空间复杂度 Code T…

【Python】 已解决:ModuleNotFoundError: No module named…

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ModuleNotFoundError: No module named… 一、分析问题背景 在使用Python进行开发时&#xff0c;有时会遇到“ModuleNotFoundError: No module named…”这样的…

创新设计策略:提升大屏幕可视化设计效果的关键方法

随着科技的不断发展和数据量的快速增长&#xff0c;数据可视化大屏在各个行业中的应用越来越广泛&#xff0c;可以帮助人们更好地理解和分析数据&#xff0c;可视化大屏设计也因此成了众多企业的需求。但很多设计师对可视化大屏设计并不了解&#xff0c;也不知道如何制作可视化…