单调栈题目总结

单调栈

496. 下一个更大元素 I

503. 下一个更大元素 II

739. 每日温度

6227. 下一个更大元素 IV

模版归纳

「单调栈」顾名思义就是具有单调性的栈结构,一般常用于找到下一个更大的元素,即当前元素右侧第一个更大的元素

看下面一个例子:2 1 2 4 3
在这里插入图片描述

我们只看得到比我们更高的元素,所以比我们矮的元素就无关紧要

下面给出「单调栈」的模版:

int[] nextGreaterElement(int[] nums) {int n = nums.length;// 存放答案的数组int[] res = new int[n];Stack<Integer> s = new Stack<>(); // 倒着往栈里放for (int i = n - 1; i >= 0; i--) {// 判定个子高矮while (!s.isEmpty() && s.peek() <= nums[i]) {// 矮个起开,反正也被挡着了s.pop();}// nums[i] 身后的更大元素res[i] = s.isEmpty() ? -1 : s.peek();s.push(nums[i]);}return res;
}

现在给几个变形

如果我们现在需要找到下一个大于等于的元素,怎么办?很简单只需要修改一个地方即可:

// 注意:我们把 s.peek() == nums[i] 的元素留下了
while (!s.isEmpty() && s.peek() < nums[i]) {// 矮个起开,反正也被挡着了s.pop();
}

如果我们现在需要找到下一个更小的元素,怎么办?很简单只需要修改一个地方即可:

while (!s.isEmpty() && s.peek() >= nums[i]) {// 高个起开,太碍眼了s.pop();
}

如果我们现在需要找到上一个更大的元素,怎么办?很简单只需要变换一下遍历顺序即可:

// 正着往栈里放
for (int i = 0; i < n; i++) {// 其他逻辑不变
}

题目实战

上面给出了「单调栈」的模版以及几种不同的变形,下面来几道题目练练手!!

下一个更大元素 I

题目详情可见 下一个更大元素 I

这个题目基本上就是一个模版题,处理上用到了一个小技巧

由于nums1nums2的子集,所以我们先求出nums2的所有下一个更大元素,用Map映射保存一下即可

public int[] nextGreaterElement(int[] nums1, int[] nums2) {Map<Integer, Integer> greaterMap = new HashMap<>();Stack<Integer> stack = new Stack<>();for (int i = nums2.length - 1; i >= 0; i--) {while (!stack.isEmpty() && stack.peek() <= nums2[i]) stack.pop();// 保存 nums2[i] 下一个更大元素greaterMap.put(nums2[i], stack.isEmpty() ? -1 : stack.peek());stack.push(nums2[i]);}int[] res = new int[nums1.length];// 寻找 nums1 中元素在 nums2 中的下一个更大元素for (int i = 0; i < nums1.length; i++) {res[i] = greaterMap.get(nums1[i]);}return res;
}
下一个更大元素 II

题目详情可见 下一个更大元素 II

这个问题加入了一个循环数组的概念,我们处理的方法就是利用 2 倍的数组即可

为了节约空间,我们可以利用「模运算」实现 2 倍数组的效果,而不需要单独开辟空间

public int[] nextGreaterElements(int[] nums) {int n = nums.length;int[] res = new int[n];Stack<Integer> stack = new Stack<>();for (int i = 2 * n - 1; i >= 0; i--) {while (!stack.isEmpty() && stack.peek() <= nums[i % n]) stack.pop();res[i % n] = stack.isEmpty() ? -1 : stack.peek();stack.push(nums[i % n]);}return res;
}
每日温度

题目详情可见 每日温度

这个问题需要让我们求与下一个更大元素的间隔,所以我们稍微转变一下栈中存储的内容即可

模版中存储的内容为num[i],这样就损失了下一个更大元素的位置信息。如果我们改为存储「下标」,既保留了位置信息,也可以通过下标获得值

public int[] dailyTemperatures(int[] temperatures) {int[] res = new int[temperatures.length];Stack<Integer> stack = new Stack<>();for (int i = temperatures.length - 1; i >= 0; i--) {while (!stack.isEmpty() && temperatures[stack.peek()] <= temperatures[i]) stack.pop();res[i] = stack.isEmpty() ? 0 : stack.peek() - i;stack.push(i);}return res;
}
下一个更大元素 IV

题目详情可见 下一个更大元素 IV

这个题目更形象的名字应该是:下下个更大的元素

public int[] secondGreaterElement(int[] nums) {int n = nums.length;int[] ans = new int[n];Arrays.fill(ans, -1);// s1 用来存储还没有遇到「比它大的下一个元素」的元素Deque<Integer> s1 = new ArrayDeque<>();// s2 用来存储遇到一个「比它大的下一个元素」的元素Deque<Integer> s2 = new ArrayDeque<>();for (int i = 0; i < nums.length; i++) {// 如果 s2 中有比 nums[i] 小的元素,说明 nums[i] 就是该元素的下下个更大的元素while (!s2.isEmpty() && nums[i] > nums[s2.peek()]) ans[s2.poll()] = nums[i];Deque<Integer> t = new ArrayDeque<>();// 如果 s1 中有比 nums[i] 小的元素,说明该元素遇到了一个「比它大的下一个元素」的元素,移到 s2 中// 注意:需要按顺序移动!!比如在 s1 中的顺序是 a1 a2 a3,那么移到 s2 中的存储顺序也应该 a1 a2 a3// 所以这里借助另外一个栈来中转一下,不然顺序会反转while (!s1.isEmpty() && nums[i] > nums[s1.peek()]) t.push(s1.poll());s1.push(i);while (!t.isEmpty()) s2.push(t.poll());}return ans;
}

其实除了用两个栈,还可以用两个堆来实现,堆比栈更好理解,但是原理都是一样的!

public int[] secondGreaterElement(int[] nums) {int n = nums.length;int[] ans = new int[n];Arrays.fill(ans, -1);// 小根堆Queue<Integer> q1 = new PriorityQueue<>((a, b) -> nums[a] - nums[b]);Queue<Integer> q2 = new PriorityQueue<>((a, b) -> nums[a] - nums[b]);for (int i = 0; i < n; i++) {int x = nums[i];while (!q2.isEmpty() && nums[q2.peek()] < x) ans[q2.poll()] = x;while (!q1.isEmpty() && nums[q1.peek()] < x) q2.offer(q1.poll());q1.offer(i); }return ans;
}

引用

  • https://lfool.github.io/LFool-Notes/algorithm/%E5%8D%95%E8%B0%83%E6%A0%88.html

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

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

相关文章

【RT-DETR有效改进】利用EMAttention加深网络深度提高模型特征提取能力(特征选择模块)

一、本文介绍 本文给大家带来的改进机制是EMAttention注意力机制,它的核心思想是,重塑部分通道到批次维度,并将通道维度分组为多个子特征,以保留每个通道的信息并减少计算开销。EMA模块通过编码全局信息来重新校准每个并行分支中的通道权重,并通过跨维度交互来捕获像素级…

【阅读笔记】红外探测器盲元国标标准及盲元识别

1、盲元定义 盲元的定义&#xff1a;盲元是红外焦平面探测器中响应过高或过低的探测单元&#xff0c;即无法准确成像的像元。盲元主要分为噪声盲元和响应率差异盲元两大类。 线阵红外探测器应用中&#xff0c;经常存在相邻的像元之间响应率有明显差异&#xff0c;其灰度响应输…

区块链技术和Hyperledger Fabric介绍

1 区块链介绍 1.1 区块链技术形成 1.1.1 起源 在比特币诞生之时&#xff0c;技术专家们开始研究比特币的底层技术&#xff0c;并抽象提取出来&#xff0c;形成区块链技术&#xff0c;或者称分布式账本技术。 1.1.2 定义 简称BT&#xff08;Blockchain technology&#xff…

防火墙综合实验

一、实验拓扑图 二、实验要求 1、办公区设备可以通过电信链路和移动链路上网(多对多的NAT、并且需要保留一个公网IP不能用来转换)。 2、分公司的设备可以通过总公司的移动链路和电信链路访问到DMZ区的http服务器 3、分公司内部的客户端可以通过公网地址访问到内部的服务器。 三…

BetaFlight开源飞控源码分析

BetaFlight开源飞控源码分析 1.整体框架2.主函数源码分析2.1.初始化2.2.运行 3.如何使用这个程序3.1.目标文件源码分析3.2.添加目标文件3.3.编译程序 4.参考文献 betaflight github开源地址&#xff1a;https://github.com/betaflight/betaflight.git BetaFlight是穿越机领域比…

【C++学习手札】多态:掌握面向对象编程的动态绑定与继承机制(初识)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;世界上的另一个我 1:02━━━━━━️&#x1f49f;──────── 3:58 &#x1f504; ◀️ ⏸ ▶️ ☰ &am…

内存基础知识

内存作用&#xff1a;用来存放数据 int x10&#xff1b; xx1&#xff1b; 这会生成一个可执行文件&#xff08;装入模块&#xff09;然后存入内存地址中 绝对装入&#xff1a;-如果知道程序放到内存中哪个位置&#xff0c;编译程序将产生绝对地址的目标代码 可重定位装入&am…

红队APT-钓鱼篇_邮件钓鱼_Ewomail系统_网页克隆

目录 演示案例:Ewomail&Swaks-邮件伪造发信人Ewomail-邮件系统-搭建&使用Ewomail&Gophish-邮件加网页钓鱼网页钓鱼-克隆修改-二维码用户劫持网页钓鱼-克隆修改-Flash升级后门上线 演示案例: Ewomail&Swaks-邮件伪造发信人 发邮件的邮箱地址如果能伪造的话&am…

解决传统单一模态难题!多模态图学习新SOTA来了!

多模态图学习是一种结合了图神经网络和多模态数据集成的学习方法&#xff0c;它涉及了数据科学、机器学习、图神经网络、多模态分析等多个前沿领域。这种跨学科特性为我们提供了丰富的创新点和探索空间。因此&#xff0c;多模态图学习也是发表高质量论文的好方向。 通过整合和…

MyBatis基础学习

一、MyBatis简介 二、MyBatis-HelloWorld 三、MyBatis-全局配置文件 四、MyBatis-映射文件 五、MyBatis-动态SQL 六、MyBatis-缓存机制 七、MyBatis-Spring整合 八、MyBatis-逆向工程 九、MyBatis-工作原理 十、MyBatis-插件开发

ch6-homework-OpenCompass大模型评测

ch6-homework-OpenCompass大模型评测 主要内容实践教程本地复现环境配置数据集下载启动评测评测结果评估结果文件说明评测配置文件详解 基础作业进阶作业 主要内容 视频网址&#xff1a;https://www.bilibili.com/video/BV1Gg4y1U7uc/?spm_id_from333.788&vd_sourceb96c7e…

Flash extractor功能介绍

Flash extractor功能介绍 Flash Extractor软件用于恢复U盘记忆卡和SSD硬盘内存芯片数据&#xff0c;每个月出现新型号的闪存设备。每个新器件有不同的内部物理和逻辑结构。我们每周都会分析和发布更新我们的软件。里面有一个支持模型库的程序。这些驱动器可以很容易地恢复 但如…