【四十八】【算法分析与设计】单调栈,单调栈模板,单调栈求个元素最近小于(等于)或者大于(等于)下标

求各个元素左边和右边的最近的小于(等于)的下标

最近的小于的计算过程:

实现的过程需要用到一个stack<==>st

黑盒:在st的元素都可以正确计算出最近小于的元素下标那么我们依次将arr中的元素入栈计即可

1.栈里面存储的是vector,vector存储的是元素的下标,同一个vector存储的这些下标对应的元素值是相同的

⒉栈从栈底到栈顶,vector对应的元素值是严格递增的,因为相同的值下标放到同一个vector里面了

3.当i下标想要入栈,必须保证i下标对应元素值大于等于栈顶vector对应的元素值或者栈空4.如果i下标对应元素值大于等于栈顶vector对应的元素值,直接入栈st.push({i))

5.如果i下标对应元素值小于栈顶vector对应的元素值,此时我们可以直到栈顶vector所有元素的左边最近小于元素下标和右边最近小于元素下标

6.左边最近小于元素下标是在栈顶下面压着的vector的最后一个元素7.右边最近小于元素下标是i

8.依次st.pop维护pop出来的vector里面所有元素最近最小下标,直到i下标对应元素值大于等于栈顶vector对应元素值,或者栈空

 
#include<bits/stdc++.h> // 包含C++标准库的所有头文件
using namespace std; // 使用标准命名空间std// 定义一个名为Solution的类
class Solution {
public:// 定义一个返回类型为vector<pair<int, int>>的成员函数getNearLessEqual,接收一个整数数组,表示获取最近的小于等于的元素下标vector<pair<int, int>> getNearLessEqual(vector<int>& arr) {vector<pair<int, int>> ret(arr.size()); // 创建一个大小与arr相同的pair数组,用于存储结果stack<int> st; // 定义一个整数栈for (int i = 0; i < arr.size(); i++) { // 遍历数组arr// 当栈不为空且当前元素小于等于栈顶元素对应的数组值时,进行循环while (!(st.empty() || arr[i] > arr[st.top()])) {int top = st.top(); st.pop(); // 取出栈顶元素并从栈中弹出int leftlessindex = st.empty() ? -1 : st.top(); // 如果栈为空,左侧最近小于等于元素的索引为-1,否则为栈顶元素索引ret[top].first = leftlessindex; // 设置结果中对应索引的第一元素ret[top].second = i; // 设置结果中对应索引的第二元素}st.push(i); // 将当前索引压入栈}// 清空栈,处理所有剩余元素while (!st.empty()) {int top = st.top(); st.pop();int leftlessindex = st.empty() ? -1 : st.top();ret[top].first = leftlessindex;ret[top].second = -1; // 由于右边没有更小的元素,所以设置为-1}return ret; // 返回结果}// 定义一个返回类型为vector<pair<int, int>>的成员函数getNearLess,功能与getNearLessEqual类似,但处理的是严格小于情况,获取最近的小于的元素下标vector<pair<int, int>> getNearLess(vector<int>& arr) {vector<pair<int, int>> ret(arr.size()); // 创建一个大小与arr相同的pair数组,用于存储结果stack<vector<int>> st; // 定义一个栈,栈中元素为整数vector,用于处理相等元素for (int i = 0; i < arr.size(); i++) { // 遍历数组arrwhile (!(st.empty() || arr[i] >= arr[st.top()[0]])) { // 当栈不为空且当前元素小于栈顶元素对应的数组值时,进行循环vector<int> top = st.top(); st.pop();int leftlessindex = st.empty() ? -1 : st.top().back(); // 如果栈为空,左侧最近小于元素的索引为-1,否则为栈顶元素的最后一个索引for (auto x : top) {ret[x].first = leftlessindex;ret[x].second = i;}}if (!st.empty() && arr[i] == arr[st.top()[0]]) { // 如果栈顶元素等于当前元素st.top().push_back(i); // 向栈顶元素的vector中添加当前索引} else {st.push({ i }); // 否则,将当前索引作为新vector压入栈}}// 清空栈,处理所有剩余元素while (!st.empty()) {vector<int> top = st.top(); st.pop();int leftlessindex = st.empty() ? -1 : st.top().back();for (auto x : top) {ret[x].first = leftlessindex;ret[x].second = -1; // 由于右边没有更小的元素,所以设置为-1}}return ret; // 返回结果}// 定义一个返回类型为vector<pair<int, int>>的成员函数getNearLess,获取最近的小于等于元素的下标的plus版本,这种版本可以快速改变为获取最近的小于的版本
vector<pair<int, int>> getNearLessEqual_1(vector<int>& arr) {vector<pair<int, int>> ret(arr.size()); // 创建一个大小与arr相同的pair数组,用于存储结果stack<vector<int>> st; // 定义一个栈,栈中元素为整数vectorfor (int i = 0; i < arr.size(); i++) { // 遍历数组arr// 当栈不为空且当前元素小于等于栈顶元素对应的数组值时,进行循环while (!(st.empty() || arr[i] > arr[st.top()[0]])) {vector<int> top = st.top(); st.pop(); // 取出栈顶元素并从栈中弹出int leftlessindex = st.empty() ? -1 : st.top().back(); // 如果栈为空,左侧最近小于等于元素的索引为-1,否则为栈顶元素的最后一个索引for (auto x : top) {ret[x].first = leftlessindex; // 设置结果中对应索引的第一元素ret[x].second = i; // 设置结果中对应索引的第二元素}}if (!st.empty() && arr[i] == arr[st.top()[0]]) { // 如果栈顶元素等于当前元素st.top().push_back(i); // 向栈顶元素的vector中添加当前索引} else {st.push({ i }); // 否则,将当前索引作为新vector压入栈}}// 清空栈,处理所有剩余元素while (!st.empty()) {vector<int> top = st.top(); st.pop();int leftlessindex = st.empty() ? -1 : st.top().back();for (auto x : top) {ret[x].first = leftlessindex;ret[x].second = -1; // 由于右边没有更小的元素,所以设置为-1}}return ret; // 返回结果}
};int main() {vector<int> arr = { 3,2,4,3,3,4,1,3,4,5 }; // 定义一个整数数组arr//以下是数组arr的索引:0 1 2 3 4 5 6 7 8 9vector<pair<int, int>> ret = Solution().getNearLess(arr); // 调用getNearLess函数,传递arr,并接收结果for (int i = 0; i < arr.size(); i++) {cout << i << ":" << "[" << ret[i].first << "," << ret[i].second << "]" << endl; // 打印每个元素的结果,显示左右侧最近的小于元素的索引}
}

求各个元素左边和右边的最近的大于(等于)的下标

只需要保证栈从栈底到栈顶是严格递减即可,其他逻辑是一样的。

单调栈的扩展

单调栈不止求最近值的大小,还可以是其他的性质,只需要满足栈底到栈顶维持这个性质的单调性即可,当加入的元素不能满足这个单调性,此时就可以依次最近的某个性质。

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

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

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

相关文章

无人机巡检技术革命性变革光伏电站运维管理

在中国广袤的大地上&#xff0c;光伏电站如雨后春笋般崛起&#xff0c;晶体硅组件板在阳光下熠熠生辉&#xff0c;为人们带来了源源不断的绿色能源。然而&#xff0c;随着光伏产业的迅猛发展&#xff0c;电站运维管理面临着前所未有的挑战。而无人机巡检技术的引入&#xff0c;…

分类预测 | Matlab实现PSO-LSSVM粒子群算法优化最小二乘支持向量机数据分类预测

分类预测 | Matlab实现PSO-LSSVM粒子群算法优化最小二乘支持向量机数据分类预测 目录 分类预测 | Matlab实现PSO-LSSVM粒子群算法优化最小二乘支持向量机数据分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现PSO-LSSVM粒子群算法优化最小二乘支持向量…

一起学习python——基础篇(19)

今天来说一下python的如何修改文件名称、获取文件大小、读取文中指定的某一行内容。 1、修改文件名称&#xff1a; import os testPath"D:/pythonFile/test.txt" testPath2"D:/pythonFile/test2.txt" #修改文件名称使用rename方法&#xff0c; #第一个参…

滑动窗口例题

一、209:长度最小的子数组 209:长度最小的子数组 思路&#xff1a;1、暴力解法&#xff1a;两层for循环遍历&#xff0c;当sum > target时计算子数组长度并与result比较&#xff0c;取最小的更新result。提交但是超出了时间限制。 class Solution {public int minSubArray…

(UDP)其他信息: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。

“System.Net.Sockets.SocketException”类型的异常在 mscorlib.dll 中发生&#xff0c;但未在用户代码中进行处理其他信息: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。这个异常表示端口已经被占用了&#xff0c;需要释放端口或者使用其他端口来建立连接。您可以…

CMake 学习笔记2

其他很好的总结 CMake教程系列-01-最小配置示例 - 知乎 CMake 保姆级教程&#xff08;上&#xff09; | 爱编程的大丙 10-补充(完结)_哔哩哔哩_bilibili 1、基本关键字 SET命令的补充 &#xff08;1&#xff09;SET命令设置执行标准 #增加-stdc11 set(CMAKE_CXX_STANDARD…

CMake快速入门

文章目录 目的环境准备快速入门总结 目的 C/C的代码可以直接使用编译工具链进行编译&#xff0c;这种方式文件一多就不方便了。也可以编写 Makefile 然后使用 make 进行编译&#xff0c;当然写 Makefile 其实也挺繁琐。对于大型项目比较流行的是编写 CMakeLists.txt 然后使用 …

Hive的分区与排序

一、Hive分区 1.引入&#xff1a; 在大数据中&#xff0c;最常见的一种思想就是分治&#xff0c;我们可以把大的文件切割划分成一个个的小的文件&#xff0c;这样每次操作一个个小的文件就会很容易了&#xff0c;同样的道理&#xff0c;在hive当中也是支持这种思想的&#xff…

2024最新在线工具箱网站系统源码

2024最新在线工具箱网站系统源码 下载地址: 2024最新在线工具箱网站系统源码-JXASP源码网https://www.jxasp.com/think-php/12489.html

记一次IP访问MySQL失败多次被自动锁定导致无法连接问题,解决方法一条SQL足以。

&#x1f469;&#x1f3fd;‍&#x1f4bb;个人主页&#xff1a;阿木木AEcru &#x1f525; 系列专栏&#xff1a;《Docker容器化部署系列》 《Java每日面筋》 &#x1f4b9;每一次技术突破&#xff0c;都是对自我能力的挑战和超越。 前言 今天下午还在带着耳机摸鱼&#xff…

OpenCV4.10使用形态运算提取水平线和垂直线

目标 在本教程中&#xff0c;您将学习如何&#xff1a; 应用两个非常常见的形态运算符&#xff08;即膨胀和侵蚀&#xff09;&#xff0c;并创建自定义内核&#xff0c;以便在水平轴和垂直轴上提取直线。为此&#xff0c;您将使用以下 OpenCV 函数&#xff1a; erode()dilate…

认识异常(2)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&a…

使用cmake进行打包,包含可执行程序和动态依赖库

平常代码开发中&#xff0c;有时候需要将写的程序打包成压缩包放到目标设备上进行运行测试。用CMake管理工程&#xff0c;实现使用make -jnproc package指令可以将工程进行打包&#xff0c;可执行文件存储在bin文件夹中&#xff0c;依赖库存储在lib文件夹中。 示例 1.工程目录结…

CSS基础之伪类选择器(如果想知道CSS的伪类选择器知识点,那么只看这一篇就足够了!)

前言&#xff1a;学习CSS就必须要学习选择器&#xff0c;在之前我们已经学习了基本选择器和复合选择器&#xff0c;但是还有几个选择器没有学习&#xff0c;这篇文章主要讲解伪类选择器。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-…

【动态规划 区间dp 位运算】100259. 划分数组得到最小的值之和

本文涉及知识点 动态规划 区间dp 位运算 LeetCode100259. 划分数组得到最小的值之和 给你两个数组 nums 和 andValues&#xff0c;长度分别为 n 和 m。 数组的 值 等于该数组的 最后一个 元素。 你需要将 nums 划分为 m 个 不相交的连续 子数组&#xff0c;对于第 ith 个子数…

【Linux】基础IO----理解缓冲区

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;理解缓冲区 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1a;Linux初阶 > 望…

网络安全(防火墙,IDS,IPS概述)

问题一:什么是防火墙,IDS,IPS? 防火墙是对IP:port的访问进行限制,对访问端口进行制定的策略去允许开放的访问,将不放开的端口进行拒绝访问,从而达到充当防DDOS的设备。主要是拒绝网络流量,阻断所有不希望出现的流程,禁止数据流量流通,达到安全防护的作用。如将一些恶…

基于SSM强国有我党建网站

摘要 国家的繁荣富强与每一个人都息息相关密不可分并且关系密切&#xff0c;无论是从事最底层的工作的城市清洁工、工地上的民工、街边自己售卖自制商品进行生活的小商小贩&#xff1b;还是有一定的经济地位可以在电视中&#xff0c;采访中&#xff0c;各类访谈节目以及广大影…

C/C++ BM23 二叉树的前序遍历

文章目录 前言题目解决方案一1.1 思路阐述1.2 源码 解决方案二2.1 思路阐述2.2 源码 总结 前言 自己在草稿纸上模拟这个遍历的过程比较简单&#xff0c;但是转移到代码上就突然会懵逼。这个在我之前学数据结构&#xff0c;做到这个实验的时候觉得很难理解。最近虽然已经入职了…

java学习之路-继承

文章目录 前言 目录 1.1继承的概念 1.2继承有什么好处&#xff0c;为何要继承 1.3继承的语句 1.4父类成员的访问 1.4.1 子类中访问父类的成员变量 1.4.2 子类中访问父类的成员方法 1.5 super关键字 2.子类构造方法 2.1如何创建构造方法 2.2创建构造方法 3.super和this 【相同点…