[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;
    }
};
相关推荐
转调几秒前
每日一练:地下城游戏
开发语言·c++·算法·leetcode
不穿格子衬衫29 分钟前
常用排序算法(下)
c语言·开发语言·数据结构·算法·排序算法·八大排序
wdxylb36 分钟前
使用C++的OpenSSL 库实现 AES 加密和解密文件
开发语言·c++·算法
aqua353574235838 分钟前
蓝桥杯-财务管理
java·c语言·数据结构·算法
CV金科38 分钟前
蓝桥杯—STM32G431RBT6(IIC通信--EEPROM(AT24C02)存储器进行通信)
stm32·单片机·嵌入式硬件·算法·蓝桥杯
sewinger1 小时前
区间合并算法详解
算法
XY.散人1 小时前
初识算法 · 滑动窗口(1)
算法
韬. .1 小时前
树和二叉树知识点大全及相关题目练习【数据结构】
数据结构·学习·算法
野草y1 小时前
数据结构(7.4_1)——B树
数据结构·b树
Word码2 小时前
数据结构:栈和队列
c语言·开发语言·数据结构·经验分享·笔记·算法