【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐

文章目录

  • 题单来源
  • 经典题单
    • 496. 下一个更大元素 I(单调栈模板题)
    • 503. 下一个更大元素 II(单调栈+循环数组)
    • 2454. 下一个更大元素 IV(第二个更大的元素:两个单调栈)
    • 456. 132 模式(单调栈找上一个更大元素+哈希表记录最小值)
    • 739. 每日温度
    • 901. 股票价格跨度
    • 1019. 链表中的下一个更大节点
    • 1124. 表现良好的最长时间段(单调栈解法⭐⭐⭐⭐⭐)
    • 1475. 商品折扣后的最终价格(单调栈找下一个更小的元素)
    • 2289. 使数组按非递减顺序排列⭐⭐⭐⭐⭐
      • 解法——等价转换 + 利用单调性🐂
  • 矩形系列
  • 字典序最小
  • 贡献法
    • 2818. 操作使得分最大(⭐质因数分解+单调栈贡献法+排序贪心)好题!
    • 更多题目

题单来源

https://leetcode.cn/problems/beautiful-towers-ii/solutions/2456562/qian-hou-zhui-fen-jie-dan-diao-zhan-pyth-1exe/

经典题单

496. 下一个更大元素 I(单调栈模板题)

https://leetcode.cn/problems/next-greater-element-i/description/
在这里插入图片描述
提示:

1 <= nums1.length <= nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 10^4
nums1和nums2中所有整数 互不相同
nums1 中的所有整数同样出现在 nums2 中

进阶:你可以设计一个时间复杂度为 O(nums1.length + nums2.length) 的解决方案吗?

预先处理出 nums2 数组中每个数字的下一个更大数字,存储在哈希表中。
生成 ans 数组时,从哈希表中逐个取结果即可。

class Solution {public int[] nextGreaterElement(int[] nums1, int[] nums2) {int n = nums1.length;Map<Integer, Integer> m = new HashMap<>();Deque<Integer> stk = new ArrayDeque<>();for (int i = 0; i < nums2.length; ++i) {while (!stk.isEmpty() && nums2[i] > stk.peek()) m.put(stk.pop(), nums2[i]);stk.push(nums2[i]);}int[] ans = new int[n];for (int i = 0; i < n; ++i) {ans[i] = m.getOrDefault(nums1[i], -1);}return ans;}
}

503. 下一个更大元素 II(单调栈+循环数组)

https://leetcode.cn/problems/next-greater-element-ii/description/

在这里插入图片描述

class Solution {public int[] nextGreaterElements(int[] nums) {int n = nums.length;int[] ans = new int[n];Arrays.fill(ans, -1);Deque<Integer> stk = new ArrayDeque<>();for (int i = 0; i < 2 * n - 1; ++i) {int id = i % n;while (!stk.isEmpty() && nums[id] > nums[stk.peek()]) ans[stk.pop()] = nums[id];stk.push(id);}return ans;}
}

2454. 下一个更大元素 IV(第二个更大的元素:两个单调栈)

https://leetcode.cn/problems/next-greater-element-iv/description/
在这里插入图片描述

提示:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^9

用两个单调栈来分别处理第一个和第二个更大,当第一次被弹出时,说明遇到了第一个更大的元素,将其弹出后放入第二个单调栈中。

在第二个单调栈被弹出的元素说明遇到了第二个更大的元素。

class Solution {public int[] secondGreaterElement(int[] nums) {int n= nums.length;int[] ans = new int[n];Arrays.fill(ans, -1);Deque<Integer> stk = new ArrayDeque<>(), stk2 = new ArrayDeque<>();for (int i = 0; i < n; ++i) {// 处理第二个单调栈while (!stk2.isEmpty() && nums[i] > nums[stk2.peek()]) {ans[stk2.pop()] = nums[i];}// 处理第一个单调栈List<Integer> ls = new ArrayList<>();while (!stk.isEmpty() && nums[i] > nums[stk.peek()]) {ls.add(stk.pop());}for (int j = ls.size() - 1; j >= 0; --j) stk2.push(ls.get(j));stk.push(i);}return ans;}
}

456. 132 模式(单调栈找上一个更大元素+哈希表记录最小值)

https://leetcode.cn/problems/132-pattern/description/

在这里插入图片描述

枚举的x作为最后一个数字,当找到上一个更大的数字时,考虑其之前出现的最小值是否小于当前值即可。

class Solution {public boolean find132pattern(int[] nums) {// 找上一个更大元素,并检查当前是否大于更大元素之前出现过的最小值int mn = Integer.MAX_VALUE;     // 记录已经枚举过的数值中的最小值Deque<Integer> stk = new ArrayDeque<>();Map<Integer, Integer> m = new HashMap<>();  // 记录各个数值之前出现的最小值for (int x: nums) {m.put(x, mn);while (!stk.isEmpty() && x >= stk.peek()) {stk.pop();}if (!stk.isEmpty() && x > m.get(stk.peek())) return true;stk.push(x);if (x < mn) mn = x;}return false;}
}

739. 每日温度

https://leetcode.cn/problems/daily-temperatures/description/

在这里插入图片描述

class Solution {public int[] dailyTemperatures(int[] temperatures) {int n = temperatures.length;int[] ans = new int[n];Deque<Integer> stk = new ArrayDeque<>();for (int i = 0; i < n; ++i) {// 维护单调递减的单调栈while (!stk.isEmpty() && temperatures[i] > temperatures[stk.peek()]) {// 当元素被弹出时,说明遇到了更大的值ans[stk.peek()] = i - stk.pop();}stk.push(i);}return ans;}
}

901. 股票价格跨度

https://leetcode.cn/problems/online-stock-span/description/
在这里插入图片描述
提示:
1 <= price <= 10^5
最多调用 next 方法 10^4 次

class StockSpanner {int t = 0;// 单调递减的单调栈Deque<Integer> stk = new ArrayDeque<>();List<Integer> ls = new ArrayList<>();public StockSpanner() {stk.push(-1);}public int next(int price) {    ls.add(price);while (stk.size() > 1 && price >= ls.get(stk.peek())) {stk.pop();}int res = t - stk.peek();stk.push(t++);return res;}
}/*** Your StockSpanner object will be instantiated and called as such:* StockSpanner obj = new StockSpanner();* int param_1 = obj.next(price);*/

1019. 链表中的下一个更大节点

https://leetcode.cn/problems/next-greater-node-in-linked-list/description/
在这里插入图片描述

提示:

链表中节点数为 n
1 <= n <= 10^4
1 <= Node.val <= 10^9

存储列表后,再使用单调栈处理。

class Solution {public int[] nextLargerNodes(ListNode head) {List<Integer> ls = new ArrayList<>();while (head != null) {ls.add(head.val);head = head.next;}int n = ls.size();int[] ans = new int[n];Deque<Integer> stk = new ArrayDeque<>();for (int i = 0; i < n; ++i) {while (!stk.isEmpty() && ls.get(i) > ls.get(stk.peek())) {ans[stk.pop()] = ls.get(i);}stk.push(i);}return ans;}
}

1124. 表现良好的最长时间段(单调栈解法⭐⭐⭐⭐⭐)

https://leetcode.cn/problems/longest-well-performing-interval/description/
在这里插入图片描述
提示:
1 <= hours.length <= 10^4
0 <= hours[i] <= 16

先正序遍历用单调栈处理,再反向遍历利用单调栈中结果。

class Solution {public int longestWPI(int[] hours) {int n = hours.length;int[] s = new int[n + 1];ArrayDeque<Integer> stk = new ArrayDeque<>();stk.push(0);// 单调递减的单调栈for (int i = 1; i <= n; ++i) {s[i] = s[i - 1] + (hours[i - 1] > 8? 1: -1);if (s[i] < s[stk.peek()]) stk.push(i);}int ans = 0;for (int i = n; i > 0; --i) {while (!stk.isEmpty() && s[i] > s[stk.peek()]) {ans = Math.max(ans, i - stk.pop());}}return ans;}
}

1475. 商品折扣后的最终价格(单调栈找下一个更小的元素)

https://leetcode.cn/problems/final-prices-with-a-special-discount-in-a-shop/description/
在这里插入图片描述

提示:
1 <= prices.length <= 500
1 <= prices[i] <= 10^3

class Solution {public int[] finalPrices(int[] prices) {int n = prices.length;// 单调栈找下一个<=的元素Deque<Integer> stk = new ArrayDeque<>();for (int i = 0; i < n; ++i) {while (!stk.isEmpty() && prices[i] <= prices[stk.peek()]) {prices[stk.pop()] -= prices[i];}stk.push(i);}return prices;}
}

2289. 使数组按非递减顺序排列⭐⭐⭐⭐⭐

https://leetcode.cn/problems/steps-to-make-array-non-decreasing/description/

在这里插入图片描述

提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^9

解法——等价转换 + 利用单调性🐂

https://leetcode.cn/problems/steps-to-make-array-non-decreasing/solutions/1524614/by-endlesscheng-s2yc/
在这里插入图片描述

class Solution {public int totalSteps(int[] nums) {int n = nums.length;// 单调递减 存储元素及其被删除的时刻Deque<int[]> stk = new ArrayDeque<>();int ans = 0;for (int i = 0; i < n; ++i) {int maxT = 0;while (!stk.isEmpty() && nums[i] >= nums[stk.peek()[0]]) {maxT = Math.max(stk.pop()[1], maxT);}if (!stk.isEmpty()) ans = Math.max(ans, maxT + 1);stk.push(new int[]{i, maxT + 1});}return ans;}
}

矩形系列

见:【算法】单调栈题单——矩阵系列

字典序最小

见:【算法】单调栈题单——字典序最小

贡献法

2818. 操作使得分最大(⭐质因数分解+单调栈贡献法+排序贪心)好题!

https://leetcode.cn/problems/apply-operations-to-maximize-score/

在这里插入图片描述
提示:
1 <= nums.length == n <= 10^5
1 <= nums[i] <= 10^5
1 <= k <= min(n * (n + 1) / 2, 10^9)

出自周赛:【力扣周赛】第 358 场周赛(大杂烩题目:质因数分解+快速幂+单调栈+贡献法)

class Solution {final long MOD = (long)1e9 + 7;final static int MX = (int)1e5 + 1;static int[] omega = new int[MX];static {for (int i = 2; i < MX; ++i) {if (omega[i] == 0) {    // i 是质数for (int j = i; j < MX; j += i) {omega[j]++;     // i 是 j 的一个质因子}}}}public int maximumScore(List<Integer> nums, int k) {int n = nums.size();int[][] scores = new int[n][2];for (int i = 0; i < n; ++i) {scores[i][0] = op(nums.get(i));         // 求质数分数}Deque<Integer> stk = new ArrayDeque<>();int[] l = new int[n], r = new int[n];       // 存储各个元素对应可以选择的l~r范围Arrays.fill(l, -1);Arrays.fill(r, n);for (int i = 0; i < n; ++i) {while (!stk.isEmpty() && scores[i][0] > scores[stk.peek()][0]) {r[stk.pop()] = i;}if (!stk.isEmpty()) l[i] = stk.peek();stk.push(i);}for (int i = 0; i < n; ++i) {scores[i][0] = nums.get(i);             // 元素的贡献scores[i][1] = (r[i] - i) * (i - l[i]); // 元素可以被选择的次数}// 排序+贪心找 k次操作对应哪些元素Arrays.sort(scores, (x, y) -> y[0] - x[0]);     // 分数倒序排序long ans = 1;for (int i = 0; i < n && k > 0; ++i) {if (scores[i][1] <= k) {ans = (ans * qmi((long)scores[i][0], (long)scores[i][1])) % MOD;} else {ans = (ans * qmi((long)scores[i][0], (long)k)) % MOD;break;}k -= scores[i][1];}return (int)ans;}// 质因数分解 得到不同质因数的数量public int op(int x) {return omega[x];}// 快速幂public long qmi(long a, long b) {long p = MOD;long res = 1 % p, t = a;while (b != 0) {if ((b & 1) == 1) res = res * t % p;t = t * t % p;b >>= 1;}return res;}
}

更多题目

更多见:【算法】贡献法相关题目练习

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

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

相关文章

C++ day44完全背包问题 零钱兑换Ⅱ 组合总和Ⅳ

完全背包&#xff1a;一个物品可以使用无数次&#xff0c;将01背包中倒序遍历背包变成正序遍历背包 遍历顺序&#xff1a;在完全背包中&#xff0c;对于一维dp数组来说&#xff0c;其实两个for循环嵌套顺序是无所谓的&#xff01; 先遍历物品&#xff0c;后遍历背包可以&#…

idea报错——Access denied for user ‘root‘@‘localhost‘ (using password: YES)

项目场景&#xff1a; 使用idea启动SpringBoot项目报错&#xff0c;可以根据提示看到是数据库的原因&#xff0c;显示使用了密码&#xff0c;具体报错信息如下&#xff1a; 解决方案&#xff1a; 第一步&#xff1a;先去配置文件里面查看连接MySQL的url是否正确&#xff0c;如果…

【蓝桥杯选拔赛真题73】Scratch烟花特效 少儿编程scratch图形化编程 蓝桥杯创意编程选拔赛真题解析

目录 scratch烟花特效 一、题目要求 编程实现 二、案例分析 1、角色分析

JDK1.8_X64在LINUX下安装

JDK1.8在LINUX下安装步骤&#xff1a; 在/usr/lib/目录下新建jvm文件夹&#xff0c;如果已有jvm文件夹&#xff0c;则将之前的JDK版本删除&#xff0c;即在jvm目录下执行命令&#xff1a;rm–rf *将JDK文件jdk-8u40-linux-x64.gz拷贝到/home/目录下&#xff1b;在/home/目录下…

华天动力-OA8000 MyHttpServlet 文件上传漏洞复现

0x01 产品简介 华天动力OA是一款将先进的管理思想、 管理模式和软件技术、网络技术相结合,为用户提供了低成本、 高效能的协同办公和管理平台。 0x02 漏洞概述 华天动力OA MyHttpServlet 存在任意文件上传漏洞,未经身份认证的攻击者可上传恶意的raq文件并执行raq文件中的任意…

PC行内编辑

点击编辑&#xff0c;行内编辑输入框出现&#xff0c;给列表的每条数据定义编辑标记&#xff0c;最后一定记得 v-model双向绑定&#xff0c;使数据回显。 步骤&#xff1a; 1、给行数据定义编辑标记 2、点击行编辑标记&#xff08;isedit&#xff09; 3、插槽根据标记渲染表单 …

数据结构:图文详解双向链表的各种操作(头插法,尾插法,任意位置插入,查询节点,删除节点,求链表的长度... ...)

目录 一.双向链表的概念 二.双向链表的数据结构 三.双向链表的实现 节点的插入 头插法 尾插法 任意位置插入 节点的删除 删除链表中第一次出现的目标节点 删除链表中所有与关键字相同的节点 节点的查找 链表的清空 链表的长度 四.模拟实现链表的完整代码 前言&am…

“此应用专为旧版android打造,因此可能无法运行”,问题解决方案

当用户在Android P系统上打开某些应用程序时&#xff0c;可能会弹出一个对话框&#xff0c;提示内容为&#xff1a;“此应用专为旧版Android打造&#xff0c;可能无法正常运行。请尝试检查更新或与开发者联系”。 随着Android平台的发展&#xff0c;每个新版本通常都会引入新的…

线程池大小设置多少,比较合适?

设置线程数的核心点 压测&#xff01;压测&#xff01;再压测&#xff01;实际对性能要求比较高的场景&#xff0c;压测是最佳的方式&#xff01; 并发编程适用于什么场景&#xff1f; CPU 密集型 对于 CPU 密集型任务&#xff0c;希望最大限度地提高 CPU 利用率&#xff0c…

每周一算法:背包问题(三)多重背包

多重背包 有 N N N件物品和一个容量是 M M M的背包。第 i i i种物品最多有 s i s_i si​件&#xff0c;每件的体积是 v i v_i vi​&#xff0c;价值是 w i w_i wi​。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输…

pytorch 模型量化quantization

pytorch 模型量化quantization 1.workflow1.1 PTQ1.2 QAT 2. demo2.1 构建resnet101_quantization模型2.2 PTQ2.3 QAT 参考文献 pytorch框架提供了三种量化方法&#xff0c;包括&#xff1a; Dynamic QuantizationPost-Training Static Quantization&#xff08;PTQ&#xff0…

DevOps搭建(三)-Git安装详细步骤

前面两篇文章我们讲了如何安装swappiness安装和虚拟机。这篇我们详细讲下如何安装Git。 1、YUM源更改为阿里云镜像源 1.1、备份CentOS-Base.repo 先备份原有的 CentOS-Base.repo 文件 sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup…

OCR原理解析

目录 1.概述 2.应用场景 3.发展历史 4.基于传统算法的OCR技术原理 4.1 图像预处理 4.1.1 灰度化 4.1.2 二值化 4.1.3 去噪 4.1.4 倾斜检测与校正 4.1.4.2 轮廓矫正 4.1.5 透视矫正 4.2 版面分析 4.2.1 连通域检测文本 4.2.2 MSER检测文本 4.3 字符切割 4.3.1 连…

2022年全国大学生数据分析大赛医药电商销售数据分析求解全过程论文及程序

2022年全国大学生数据分析大赛 医药电商销售数据分析 原题再现&#xff1a; 问题背景   20 世纪 90 年代是电子数据交换时代&#xff0c;中国电子商务开始起步并初见雏形&#xff0c;随后 Web 技术爆炸式成长使电子商务处于蓬勃发展阶段&#xff0c;目前互联网信息碎片化以…

数组逆序重放

数组逆序重放的意思是将数组的元素逆序排列&#xff0c;然后重新放回原数组中。这个操作可以在很多编程语言中实现&#xff0c;例如Python、Java等。 下面是一个Python的示例代码&#xff0c;可以实现这个操作&#xff1a; def reverse_and_rearrange(arr): # 反转数组 …

git rebase冲突说明(base\remote\local概念说明)

主线日志及修改 $ git log master -p commit 31213fad6150b9899c7e6b27b245aaa69d2fdcff (master) Author: Date: Tue Nov 28 10:19:53 2023 08004diff --git a/123.txt b/123.txt index 294d779..a712711 100644 --- a/123.txtb/123.txt-1,3 1,4 123 4^Mcommit a77b518156…

分享几个电视颜色测试图形卡

介绍 本文分享几个常见的电视颜色测试图形卡和一段matlab程序&#xff0c;完成JPG转FPGA烧写文件&#xff0c;便于把彩色图片预装载到FPGA内。 电视颜色测试图形卡 一种专业检测电视显示效果的工具。它通常由一张卡片和一些色块组成&#xff0c;可以根据标准色彩空间和颜色渐…

Web安全漏洞分析-XSS(中)

随着互联网的迅猛发展&#xff0c;Web应用的普及程度也愈发广泛。然而&#xff0c;随之而来的是各种安全威胁的不断涌现&#xff0c;其中最为常见而危险的之一就是跨站脚本攻击&#xff08;Cross-Site Scripting&#xff0c;简称XSS&#xff09;。XSS攻击一直以来都是Web安全领…

版本依赖冲突问题排查过程记录

问题 开发平台在集成minio时&#xff0c;pom引入了sdk。 <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.7</version> </dependency>在调用上传文件API时&#xff0c;控制台报错&…

如何开启Windows Server 2016 远端桌面

使用GUI 设定 服务器管理器–> 本地服务器–> 远端桌面 启用远端桌面 远端–> 允许远端连线至此电脑 会提示防火墙设定跟电源设定 防火墙之前已经关闭了 完成