单调栈笔记

单调栈

  • 1.每日温度
  • 2.下一个更大元素 I
  • 3.下一个更大的元素
  • 4.接雨水
  • 5.柱状图中最大的矩形

单调栈正如其名字,用一个栈(能够实现栈性质的数据结构就行)来存储元素,存储在栈中的元素保持单调性(单调递增或者是单调递减)单调常用来解决寻找任一个元素左边或者右边第一个比自己小或者大的元素位置,大家可以想象看,如果是只需要找某一个元素的话,我们遍历一次数组就好了,但是如果是找数组中所有元素的左边或者右边第一个比自己小或者大的元素位置时,那么每找一次遍历一次数组的话,这样会是O(n^2)的时间复杂度,单调栈就是来实现一次遍历解决问题的办法。

具体如何实现,以及单调栈如何维护的,请看下面的题目

1.每日温度

在这里插入图片描述这个题目是单调栈的经典应用,我们需要找到下一个比当前天气温高的日子出现在几天之后。

1.单调栈中存储的是数组下标index
2.单调栈中:栈顶到栈底保持单调递减

class Solution {
public:vector<int> dailyTemperatures(vector<int>& temperatures) {vector<int> ans(temperatures.size(), 0);//定义一个单调栈vector<int> stack;for(int i = 0; i < temperatures.size(); i++){if(stack.size() == 0 || temperatures[stack.back()] >= temperatures[i]){stack.push_back(i);}else{//将单调栈中所有小于当前元素的栈针弹出来(保持单调性)while(stack.size() > 0 && temperatures[stack.back()] < temperatures[i]){int index = stack.back();stack.pop_back();ans[index] = i - index; }//将当前元素添加到栈中stack.push_back(i);}}return ans;}
};

2.下一个更大元素 I

在这里插入图片描述
这个题目可以利用我们普通暴力解法(多层循环)实现,但是下面给出的是单调栈的实现

class Solution {
public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {vector<int> stack;//单调栈unordered_map<int, int> m; //存储nums2中 nums2[i]和i的键值对vector<int> first_max_index(nums2.size(), -1);for(int i = 0; i < nums2.size(); i++){//先将nums2[i]和i的键值对存储好m[nums2[i]] = i;//开始单调栈的过程if(stack.empty() || nums2[stack.back()] >= nums2[i]){stack.push_back(i);}else{while(!stack.empty() && nums2[stack.back()] < nums2[i]){int index = stack.back();stack.pop_back();first_max_index[index] = i;}stack.push_back(i);}}vector<int> ans(nums1.size(), -1);for(int i = 0; i < nums1.size(); i++){//nums1[i]在nums2中下标int index = m[nums1[i]];//获得nums2[index]右侧第一个大于的元素int first_index = first_max_index[index];if(first_index != -1) ans[i] = nums2[first_index];}return ans;}
};

3.下一个更大的元素

在这里插入图片描述这个题目在上一个题目的基础上,将数组收尾相连了起来,而且数组长度也变大了,所以就不能够通过暴力求解了,只能够通过单调栈来实现。

思路:直接在原数组再拼接一个原数组(解决首尾相连),然后通过单调栈来找下一个更大元素

class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {int n = nums.size();//将循环数组给铺平for(int i = 0; i < n; i++){nums.push_back(nums[i]);}vector<int> ans(n * 2, -1);vector<int> stack;for(int i = 0; i < 2 * n; i++){if(stack.empty() || nums[stack.back()] >= nums[i]){stack.push_back(i);}else{while(!stack.empty() && nums[stack.back()] < nums[i]){int index = stack.back();stack.pop_back();ans[index] = nums[i];}stack.push_back(i);}}for(int i = 0; i < n; i++){ans.pop_back();}// 写法二:最后再把结果集即ans数组resize到原数组大小//ans.resize(nums.size() / 2);return ans;}
};

方法优化,不通过拼接解决收尾相连

// 版本二
class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {vector<int> result(nums.size(), -1);if (nums.size() == 0) return result;stack<int> st;for (int i = 0; i < nums.size() * 2; i++) {// 模拟遍历两边nums,注意一下都是用i % nums.size()来操作while (!st.empty() && nums[i % nums.size()] > nums[st.top()]) {result[st.top()] = nums[i % nums.size()];st.pop();}st.push(i % nums.size());}return result;}
};

4.接雨水

在这里插入图片描述
这个题目常见的有两种实现方案,一种是双指针实现,另外一种是单调栈实现,这个两种方法实现的区别就在于前者是按照列为主来计算面积的,后者是以行为主来计算面积。

双指针:通过前缀数组和后缀数组实现寻在某列两侧高度最大的列

在这里插入图片描述

# python实现代码,c++实现逻辑也是一样的
class Solution:def trap(self, height: List[int]) -> int:n = len(height)prefix, suffix = [0] * n, [0] * n# 前缀最大值prefix[0] = height[0]for i in range(1, n):prefix[i] = max(prefix[i - 1], height[i])# 后缀最大值suffix[-1] = height[-1]for i in range(n - 2, -1, -1):suffix[i] = max(suffix[i + 1], height[i])# 每一个格子对应能解多少水等于前后缀最大值的中的最小值 - 柱子高度ans = 0for h, pre, suf in zip(height, prefix, suffix):ans += min(pre, suf) - hreturn ans

单调栈:单调栈的计算是将每行的面积累加完成的

在这里插入图片描述

class Solution {
public://单调栈实现int trap(vector<int>& height) {stack<int> st;st.push(0);int sum = 0;for(int i = 0; i < height.size(); i++){while(!st.empty() && height[i] > height[st.top()]){int mid = st.top();st.pop();if(!st.empty()){int h = min(height[st.top()], height[i]) - height[mid];int w = i - st.top() - 1;sum += h * w;}}st.push(i);}return sum;}
};

5.柱状图中最大的矩形

在这里插入图片描述本次的解题思路和上题接雨水是一样的,但是本题中,我们需要关注的是矮的柱子(短板原理),上一题是关注高的柱子。同上有两种解法,下面给出的是单调栈的解法。(这个题目比上个题目要难一点,请注意如何处理收尾使得遍历逻辑连贯)

class Solution {
public:int largestRectangleArea(vector<int>& heights) {stack<int> st;//首部加入0是为了能够在某升序数组的情况下获得左边界;尾部加入0是为了能够方便循环的进行(能够将所有元素弹出计算)heights.insert(heights.begin(), 0);//数组头部加入元素0heights.insert(heights.end(), 0);//数组尾部加入元素0st.push(0);int result = 0;for(int i = 1; i < heights.size(); i++){while(heights[i] < heights[st.top()]){int mid = st.top();st.pop();int w = i - st.top() - 1;int h = heights[mid];result = max(result, w * h);}st.push(i);}return result;}
};

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

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

相关文章

信息检索与数据挖掘 | (十)线性回归与逻辑回归

文章目录 &#x1f4da;线性回归算法流程&#x1f4da;Bias and variance&#x1f4da;过拟合&欠拟合&#x1f4da;逻辑回归算法流程 &#x1f4da;线性回归算法流程 ybwx 使用loss function L来评估函数的好坏 从而我们要选择使L最小的模型参数w,b 使用梯度下降的方法…

JAVA 学习 面试(六)数据类型与方法

数据类型 基本数据类型 为什么float3.4报错 3.4 默认是浮点double类型的&#xff0c;如果赋值给float是向下转型&#xff0c;会出现精度缺失&#xff0c;&#xff0c;需要强制转换 Switch支持的数据类型&#xff1f; byte、short、int、char 、 enum 、 String 基本类型与包…

trino-435: trino接入TIDB数据源

文章目录 一、TIDB介绍二、TIDB源接入流程三、遇到的错误1、数据源注册:2、查询表数据一、TIDB介绍 二、TIDB源接入流程 三、遇到的错误 1、数据源注册: http://localhost:8080/v1/catalog/register?name=tidb_test {"connector.name":"tidb",&quo…

SpringBoot整合QQ邮箱发送验证码

一、QQ开启SMTP 打开QQ邮箱&#xff0c;点击设置&#xff0c;进入账号&#xff0c;往下滑后&#xff0c;看见服务状态后&#xff0c;点击管理服务 进入管理服务后&#xff0c;打开服务&#xff0c;然后获取授权码 二 、导入依赖 <!-- 邮箱--><dependency>&…

php低版本(7.4)配置过程中遇到的问题及基本解决手段

目前php不支持较低版本的安装&#xff0c;如果安装低版本必须借助第三方库shivammathur //将第三方仓库加入brewbrew tap shivammathur/php //安装PHPbrew install shivammathur/php/php7.4 可能出现的问题 像这样突然中止然后报错&#xff0c;一般是网络问题&#xff0c;或…

Random Sprays Retinex 传统的图像增强算法RSR

文章目录 前言1、Random Sprays Retinex 概况2、Random Sprays Retinex 具体实现2.1、喷雾的生成2.2、径向密度函数的确定2.3、像素的选择2.4、亮度的计算2.5、参数的调整 3、Random Sprays Retinex 算法效果的表现4、Random Sprays Retinex 现存的问题 前言 Random Spray Reti…

C++面试宝典第24题:袋鼠过河

题目 一只袋鼠要从河这边跳到河对岸,河很宽,但是河中间打了很多桩子。每隔一米就有一个桩子,每个桩子上都有一个弹簧,袋鼠跳到弹簧上就可以跳得更远。每个弹簧力量不同,用一个数字代表它的力量,如果弹簧力量为5,就代表袋鼠下一跳最多能够跳5米;如果为0,就会陷进去无法…

代码中遇到的问题2

目录 记录: 好处&#xff1a; 问题一&#xff1a; 解答: 问题二: 解答: 常见类型问题: 记录: string connStr ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; 在代码中写上这段代码&#xff0c;将连接数据库的代码语句放到&#xff…

关于在微信小程序中使用taro + react-hook后销毁函数无法执行的问题

问题&#xff1a; 在 taro中使用navigageTo() 跳转路由后hook中useEffect 的return函数没有执行 没有执行return函数 框架版本&#xff1a; tarojs: 3.6 react: 18.0 原因&#xff1a; 使用navigateTo() 跳转路由的话并不会销毁页面和组件&#xff0c;会加入一…

性能优化-OpenCL运行时API介绍

「发表于知乎专栏《移动端算法优化》」 本文首先给出 OpenCL 运行时 API 的整体编程流程图&#xff0c;然后针对每一步介绍使用的运行时 API&#xff0c;讲解 API 参数&#xff0c;并给出编程运行实例。总结运行时 API 使用的注意事项。最后展示基于 OpenCL 的图像转置代码。在…

L1-093 猜帽子游戏(Java)

宝宝们在一起玩一个猜帽子游戏。每人头上被扣了一顶帽子&#xff0c;有的是黑色的&#xff0c;有的是黄色的。每个人可以看到别人头上的帽子&#xff0c;但是看不到自己的。游戏开始后&#xff0c;每个人可以猜自己头上的帽子是什么颜色&#xff0c;或者可以弃权不猜。如果没有…

17β-Estradiol high sensitivity ELISA kit

高灵敏ELISA试剂盒&#xff0c;可检测到低至14 pg/ml的17β-雌二醇 雌二醇(estradiol) 是由卵巢内卵泡的颗粒细胞分泌的类固醇激素&#xff0c;是主要的雌激素&#xff0c;负责调节女性特征、附属性器官的成熟和月经-排卵周期&#xff0c;促进乳腺导管系统的产生&#xff0c;有…

JanusGraph图数据库的应用以及知识图谱技术介绍

目录 JanusGraph介绍 JanusGraph 的主要优势 JanusGraph的应用&#xff1a; JanusGraph 的行业应用&#xff1a; 架构概览 分布式技术应用 横向扩展能力 程序与janus的交互 Janus与图数据库相关概念 结构化存储 图结构存储 实体关系存储 知识存储技术 JanusGraph介…

软考案例分析题万金油汇总

目录 二、范围管理存在的问题 三、变更管理可能存在的问题 四、招标问题 五、风险管理可能存在的问题 六、采购管理中存在的问题 七、配置管理可能出现的问题 八、配置管理混乱和配置管理相关案例回答 九、项目收尾可能存在的问题 十、人力资源管理存在的问题 十一、…

【MySQL】体系结构

文章目录 体系结构图存储引擎查询建表语句查看当前数据库可支持的存储引擎InnoDB逻辑存储结构架构内存结构磁盘结构体系结构图 体系结构说明 连接层 最上层是一些客户端和链接服务,主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端…

【大数据精讲】全量同步与CDC增量同步方案对比

目录 背景 名词解释 问题与挑战 FlinkCDC DataX 工作原理 调度流程 五、DataX 3.0六大核心优势 性能优化 背景 名词解释 CDC CDC又称变更数据捕获&#xff08;Change Data Capture&#xff09;&#xff0c;开启cdc的源表在插入INSERT、更新UPDATE和删除DELETE活动时…

08-微服务Seata分布式事务使用

一、分布式事务简介 1.1 概念 事务ACID&#xff1a; A&#xff08;Atomic&#xff09;&#xff1a;原子性&#xff0c;构成事务的所有操作&#xff0c;要么都执行完成&#xff0c;要么全部不执行&#xff0c;不可能出现部分成功部分失 败的情况。 C&#xff08;Consistency&…

npm install运行报错npm ERR! gyp ERR! not ok问题解决

执行npm install的时候报错&#xff1a; npm ERR! path D:..\node_modules\\**node-sass** npm ERR! command failed ...npm ERR! gyp ERR! node -v v20.11.0 npm ERR! gyp ERR! node-gyp -v v3.8.0 npm ERR! gyp ERR! not ok根据报错信息&#xff0c;看出时node-sass运行出现…

写点东西《检查和更新NPM包》

写点东西《检查和更新NPM包》 检查和更新 NPM 包 TL;DR&#xff1b; 用于检查和更新软件包的 NPM 命令# [](#npm-outdated)npm outdatednpm updatenpm update --save-dev --savenpm update -g npm-check-updates 检查和更新软件包的命令npm install -g npm-check-updatesnpx np…

Idea Community社区版如何添加Run Dashboard

最近在学习spring cloud&#xff0c;跟着视频添加run dashboard&#xff0c;发现里面介绍的方法无法适用于idea community(社区版)。 然后自己研究了一下&#xff0c;成功添加&#xff0c;下面分享自己的方法。 如图&#xff0c;我的项目里添加了两个module&#xff0c;我想通…