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

文章目录

  • 题单来源
  • 经典题单
    • 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.mzph.cn/news/194777.shtml

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

相关文章

操作系统||经典进程同步问题之读者-写者问题

一个数据文件或记录可被多个进程共享 【问题描述】 有读者和写者两组并发进程&#xff0c;共享一个文件&#xff0c;当两个或两个以上的读进程同时访问共享数据时不会产生副作用&#xff0c;但若有某个写进程和其他进程&#xff08;读进程或写进程&#xff09;同时访问共享数…

Autosar COM通信PDU

文章目录 Autosar 中各个PDU所在示意图PDU的分类PDU 和 SDU 的关系I-PDUN-PDUL-PDU相关协议其他参考 Autosar 中各个PDU所在示意图 PDU的分类 在Autosar 中&#xff0c;主要有 I-PDU、N-PDU和 L-PDU 三种。 L-PDU&#xff1a;Data Link Layer PDU&#xff0c;数据链路层PDUN-…

[C/C++]数据结构 关于二叉树的OJ题(利用分治思想解决难题)

题目一: 单值二叉树 &#x1f6a9;⛲&#x1f31f;⚡&#x1f966;&#x1f4ac; &#x1f6a9;题目链接:力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 ⛲题目描述: 如果二叉树每个节点都具有相同的值&#xff0c;那么该二叉树就是单值二叉树。…

制作飞腾(arm)芯片架构的nexus镜像

nexus官方没有arm架构的镜像&#xff0c;下面介绍一种自己制作镜像的方式 1、事先准备 在一个arm架构机器上安装docker下载nexus的linux版(https://www.sonatype.com/download-oss-sonatype)下载centos的arm架构镜像(docker pull centos-centos8.4.2105)下载arm版本的java8(ht…

POJ 3734 Blocks 动态规划(矩阵的幂)

一、题目大意 我们要给排成一行的区块涂颜色&#xff0c;可以选择红、绿、蓝、黄四种&#xff0c;要求红和绿的块都必须是偶数个&#xff0c;求出最终的涂色方式&#xff0c;对10007取余。 二、解题思路 我们设三个数列A&#xff0c;B和C&#xff1a; 1、A代表红色和绿色都…

SpringSecurity 三更草堂 学习笔记

SpringSecurity从入门到精通 0. 简介 Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro&#xff0c;它提供了更丰富的功能&#xff0c;社区资源也比Shiro丰富。 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的…

前端笔记(二):CSS 选择器与特性

CSS&#xff08;层叠样式表&#xff09;是一种样式表语言&#xff0c;用于描述HTML或XML文档的呈现方式。它定义了如何在屏幕、纸张或其他媒体上显示文档的样式、布局和外观。 里面的代码由 选择器 { } 组成 体验 CSS CSS 可以让我们界面变得更加美观&#xff0c;这是 CSS 的…

同旺科技 分布式数字温度传感器 -- Modbus Poll测试

内附链接 1、数字温度传感器 主要特性有&#xff1a; ● 支持PT100 / PT1000 两种铂电阻&#xff1b; ● 支持 2线 / 3线 / 4线 制接线方式&#xff1b; ● 支持5V&#xff5e;17V DC电源供电&#xff1b; ● 支持电源反接保护&#xff1b; ● 支持通讯波特率1200bps、2…

YOLOv8 区域计数 | 入侵检测 | 人员闯入

大家好,昨天的 YOLOv8 新增加了一个功能,区域计数,用这个功能我们能实现很多的任务, 比如入侵检测,流量统计,人员闯入等,使用方式也非常的方便,但是一定要使用最新版的 YOLOv8 代码(2023/12/03更新的代码)。 低版本是不具备这个功能的,上面是演示效果。 使用非常的方…

计算机网络TCP篇③问答篇

目录 一、如何理解 TCP 是面向字节流协议 先来说说为什么 UDP 是面向报文的协议&#xff1f; 如果收到了两个 UDP 报文&#xff0c;操作系统是如何区分开的呢&#xff1f; 再说说为什么 TCP 是面向字节流的协议&#xff1f; 二、如何解决粘包问题&#xff1f; ①、固定消…

【强化学习算法】Q-learning原理及实现

实现代码github仓库&#xff1a;RL-BaselineCode 代码库将持续更新&#xff0c;希望得到您的支持⭐&#xff0c;让我们一起进步&#xff01; 文章目录 1. 原理讲解1.1 Q值更新公式1.2 ε-greedy随机方法 2. 算法实现2.1 算法简要流程2.2 游戏场景2.3 算法实现 3. 参考文章 1. 原…

DBS note7 (end):DB Design

目录 一、前言 二、引言 三、Entity-Relationship Models&#xff08;实体-关系模型&#xff09; 1、关系约束 三、函数依赖和正则化 1、BCNF分解 2、无损分解 3、依赖关系保留分解 一、前言 略读过一遍CS186&#xff0c;对于CS186来说&#xff0c;绝对不止这 7 篇笔记…

10. 哈希表

哈希表(hash table)&#xff0c;又称散列表&#xff0c;其通过建立键 key 与值 value 之间的映射&#xff0c;实现高效的元素查询。具体而言&#xff0c;我们向哈希表输入一个键 key &#xff0c;则可以在 \(O(1)\) 时间内获取对应的值 value 。 给定 n 个学生&#xff0c;每个…

Docker Registry(镜像仓库)——4

目录&#xff1a; 什么是 Docker Registry镜像仓库生活案例镜像仓库分类镜像仓库工作机制常用的镜像仓库镜像仓库命令 命令清单docker logindocker pulldocker pushdocker searchdocker logout镜像命令[部分] docker imagesdocker image inspectdocker tag容器命令[部分] dock…

通义灵码简单使用例子

首先我们需要了解到通义灵码的能力&#xff1a; 行/函数级实时续写&#xff1a; 当我们在 idea进行代码编写时(确认开启了自动云端生成的模式)&#xff0c;通义灵码会根据当前代码文件及相关代码文件的上下文&#xff0c;自动为你生成代码建议。你可以不用&#xff0c;也可以t…

Verilog 入门(九)(建模实例)

文章目录 建模的不同方式条件操作建模通用移位寄存器状态机建模Moore 有限状态机建模Mealy 型有限状态机建模 建模的不同方式 分别使用数据流方式、行为方式和结构方式对下图所示的电路进行建模&#xff1a; 数据流方式&#xff1a;使用连续赋值语句对电路建模 module Save_M…

viple模拟器使用(四):unity模拟器中实现两距离局部最优迷宫算法

名字解读 两距离&#xff1a;指的是左侧距离和右侧距离 局部最优&#xff1a;对当前状态来说最好的选择&#xff0c;至于整体能不能达到最优&#xff0c;是无法确定的。 从节点1到节点5&#xff0c;一共有3条路 第1条路线&#xff1a;1→2→4→5&#xff0c;对应的花销是&…

机器学习笔记 - 什么是模型量化压缩技术?

一、简述 我们都知道现实世界是连续的状态,而计算机世界是离散的状态,这是什么意思呢?我们看一下下图,最右边的马力欧(高清)的状态,可以想象现实世界是连续的状态,而电脑世界在图像上呈现的是一格一格子的状态(左图)是离散的状态。 所以在计算机世界如果想要…

51单片机应用从零开始(十)·指针

指针 C语言指针是一种保存变量地址的数据类型。它可以让程序直接访问内存中的数据&#xff0c;而不需要通过变量名来访问。指针变量存储的是一个地址&#xff0c;这个地址指向内存中的某个位置&#xff0c;该位置存储了一个值。 在C语言中&#xff0c;可以使用&运算符取得一…

【计算机网络笔记】物理层——数据通信基础

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…