[H单调栈] lc3113. 边界元素是最大值的子数组数目(单调栈+问题转换+模板题+好题)

文章目录

    • [1. 题目来源](#1. 题目来源)
    • [2. 题目解析](#2. 题目解析)

1. 题目来源

链接:3113. 边界元素是最大值的子数组数目

2. 题目解析

单调栈问题,代码很短,看看是怎么一步步思考出来的:

  • 首先,子数组问题,可以优先考虑枚举 右端点(枚举左端点也是可以的)。枚举右端点的好处是,枚举到 rj 时,我的 li 已经被枚举过了,我只需要从 "满足条件" 的 li 中挑选出来符合的结果即可。这里的条件,实际上就是题目中的待发现的性质。
  • 对于本题,先举个例子:4, 3, 1, 2, 1 顺序枚举时,有 4,3,1,当遇见 2 时中间这个 1 是完全没有机会的,因为左边是比它大的数,右边也有个比它大的数,它已经不可能是一个子数组的边界了。
    • 所以,可以不用考虑这个 1。
    • 根据这个性质,很明显,只需要维护一个从左到右的单调栈就行了。
    • 栈内放什么元素呢?应该放的是 [数字, 数字出现的次数],因为题目要求的子数组两头是一样的数字。
    • 再发现,当我们有了单调栈,现在枚举到 x 时,x 和栈顶有三个关系。
      • x > top:直接出栈即可
      • x == top:答案累计 top 出现的次数即可,并需要将 top 的次数需要加 1。
      • x < top:入栈,次数为 1。

代码实现技巧:

  • res 初始化为 n,因为单个元素也算一种子数组。
  • 单调栈放入一个正无穷大哨兵,防止栈为空。就不用做 stk.size() 的判断了。
    • 这是一个很强的技巧哈,积累一下。

  • 时间复杂度 : O ( n ) O(n) O(n)
  • 空间复杂度 : O ( 1 ) O(1) O(1)

单调栈,未加哨兵:

cpp 复制代码
class Solution {
public:
    long long numberOfSubarrays(vector<int>& nums) {
        typedef long long LL;
        int n = nums.size();

        LL res = n;
        stack<pair<int, int>> stk;
        for (int i = 0; i < n; i ++ ) {
            int x = nums[i];
            while (stk.size() && stk.top().first < x) stk.pop();
            if (stk.size() && stk.top().first == x) {
                res += stk.top().second;
                stk.top().second ++ ;
                continue;
            } 

            stk.push({x, 1});
        }

        return res;
    }
};

单调栈,哨兵优化,避免判断栈是否为空:

cpp 复制代码
class Solution {
public:
    long long numberOfSubarrays(vector<int>& nums) {
        typedef long long LL;
        int n = nums.size();

        LL res = n;
        stack<pair<int, int>> stk;
        stk.push({1e9, 0}); // 添加哨兵元素,保证单调栈不为空
        for (int i = 0; i < n; i ++ ) {
            int x = nums[i];
            while (stk.top().first < x) stk.pop();
            if (stk.top().first == x)  res += stk.top().second ++ ;
            else stk.push({x, 1});
        }

        return res;
    }
};
相关推荐
凌肖战3 分钟前
力扣网编程55题:跳跃游戏之逆向思维
算法·leetcode
88号技师1 小时前
2025年6月一区-田忌赛马优化算法Tianji’s horse racing optimization-附Matlab免费代码
开发语言·算法·matlab·优化算法
ゞ 正在缓冲99%…1 小时前
leetcode918.环形子数组的最大和
数据结构·算法·leetcode·动态规划
Kaltistss2 小时前
98.验证二叉搜索树
算法·leetcode·职场和发展
知己如祭2 小时前
图论基础(DFS、BFS、拓扑排序)
算法
mit6.8242 小时前
[Cyclone] 哈希算法 | SIMD优化哈希计算 | 大数运算 (Int类)
算法·哈希算法
c++bug2 小时前
动态规划VS记忆化搜索(2)
算法·动态规划
哪 吒2 小时前
2025B卷 - 华为OD机试七日集训第5期 - 按算法分类,由易到难,循序渐进,玩转OD(Python/JS/C/C++)
python·算法·华为od·华为od机试·2025b卷
努力写代码的熊大3 小时前
单链表和双向链表
数据结构·链表
军训猫猫头3 小时前
1.如何对多个控件进行高效的绑定 C#例子 WPF例子
开发语言·算法·c#·.net