当前位置: 首页 > news >正文

算法模板之单调栈解密 | 图文详解

在这里插入图片描述
🌈个人主页:聆风吟
🔥系列专栏:算法模板、数据结构
🔖少年有梦不应止于心动,更要付诸行动。


文章目录

  • 📋前言
  • 一. ⛳️单调栈讲解
    • 1.1 🔔单调栈的定义
    • 1.2 🔔如何维护一个单调栈
    • 1.3 🔔单调栈的用途
    • 1.4 🌟模板总结(重点)🌟
    • 1.4 🔔单调栈的实例练习
  • 📝全文总结

📋前言

    💬 hello! 各位铁子们大家好哇,今天作者给大家带来了单调栈的算法解密,因为前面我们已经讲解了用数组模拟栈过程,今天单调栈也是采用数组模拟,在此就不多做叙述有需要补漏的小伙伴可以自行前往下面专栏去浏览。
    📚 系列专栏:本期文章收录在《算法模板》,大家有兴趣可以浏览和关注,后面将会有更多精彩内容!
    🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝



一. ⛳️单调栈讲解

1.1 🔔单调栈的定义

定义:栈内的元素是单调递增或单调递减的栈。


1.2 🔔如何维护一个单调栈

  • 单调递增栈:在保持栈内元素单调递增的前提下,如果栈顶元素大于要入栈的元素,将栈顶元素弹出,将新元素入栈。
  • 单调递减栈:在保持栈内元素单调递减的前提下,如果栈顶元素小于要入栈的元素,则将栈顶元素弹出,将新元素入栈。

1.3 🔔单调栈的用途

在这里插入图片描述

由上图可以看出,对于栈内元素来说:

  • 在栈内左边的数就是数组中左边第一个比自己小的元素;
  • 但元素被弹出时,遇到的就是数组中右边第一个比自己小的元素。

对于将要入栈的元素来说:在对栈进行更新后(即弹出了所有比自己大的元素),此时栈顶元素就是数组中左侧第一个比自己小的元素;


在这里插入图片描述

由上图可以看出,对于栈内元素来说:

  • 在栈内左边的数就是数组中左边第一个比自己大的元素;
  • 但元素被弹出时,遇到的就是数组中右边第一个比自己大的元素。

对于将要入栈的元素来说:在对栈进行更新后(即弹出了所有比自己小的元素),此时栈顶元素就是数组中左侧第一个比自己大的元素;

    由此,我们可以看出单调栈的用途是:给定一个序列,指定一个序列中的元素,求解该元素左侧或右侧第一个比自己小或大的元素。

1.4 🌟模板总结(重点)🌟

本文总结的模板是找出每个数左边离它最近的比它大或小的数,右边的可以自行推导(单看模板比较抽象,建议看完下面的题目,在返回来看)

//常见模型:找出每个数左边离它最近的比它大/小的数
int tt = 0;//栈顶指针
for (int i = 1; i <= n; i ++ )
{//check函数是判断查找://1. 每个数左边第一个比它小的数//2. 还是每个数左边第一个比它大的数while (tt && check(stk[tt], i)) tt -- ;stk[ ++ tt] = i;
}

1.4 🔔单调栈的实例练习

⌈ 在线OJ链接 ⌋

题目:
在这里插入图片描述

输入样例:

5
3 4 2 7 5

输出样例:

-1 3 -1 2 2

解题思路:
    我们还是以上面的 3 4 2 7 5 来举例分析,开始遍历 3 这个元素,此时栈为空,那就表明 3 这个元素左侧没有比自身小的元素,将结果 -1 记录一下(或者直接输出)。然后将 3 压入栈中。遍历到 4 时发现 4 大于栈顶的元素 3,表明 4 这个元素左侧第一个比自身小的元素是 3,将结果 3 记录一下(或者直接输出)。遍历到 2 时,发现 2 小于栈顶的元素 4,4 是不可能作为结果输出的,所以需要将栈顶的 4 弹出。弹出之后栈顶的元素就是 3 ,同样 2 仍然小于 3,需要再次将 3 弹出。此时我们发现栈里面已经没有元素了,说明 2 的左侧没有比自身小的元素,将结果 -1 记录一下。然后将 2 压入栈中。其他的元素同理便可以得出,下面给出了动图,这里就不一一讲解了!
在这里插入图片描述

c++代码:

#include <iostream>using namespace std;
const int N = 100010;
int stk[N], tt;int main()
{int n = 0;cin >> n;for(int i = 0; i < n; i++){int x = 0;cin >> x;//如果栈顶元素大于当前待入栈元素,则出栈while(tt && stk[tt] >= x) tt--;if(tt){//栈顶元素就是左侧第一个比它小的元素。cout << stk[tt] << " ";}else {//如果栈空,则没有比该元素小的值。cout << "-1" << " ";}//将当前元素加入单调栈中stk[++tt] = x;}return 0;
}


📝全文总结

本文主要讲解:

  1. 单调栈的定义:栈内的元素是单调递增或单调递减的栈;
  2. 如何维护一个单调栈;
  3. 单调栈的用途:给定一个序列,指定一个序列中的元素,求解该元素左侧或右侧第一个比自己小或大的元素;
  4. 实例练习

     文章可能会有出现错误的地方,欢迎大家在评论区里指正,非常感谢。同时希望大家课下能够多敲多练,孰能生巧。

     今天的内容就到这里了,你对今天的内容是否有所掌握?如果还有疑问的话请在评论区里多多提问,大家可以一起帮你解决,让我们共同进步。创作不易,如果对你有用的的话点个赞支持下作者,你们的支持是作者创作最大的动力。关注我不迷路,让我们下期再见✋✋。

http://www.lryc.cn/news/219646.html

相关文章:

  • 187.重复的 DNA 序列
  • Sentinel黑白名单授权规则解读
  • Spring底层原理学习笔记--第二讲--(BeanFactory实现与ApplicaitonContext实现)
  • 云原生|kubernetes |kubelet服务加入系统守护进程supervisor(centos7系统下演示通过)
  • onnx 模型加载部署运行方式
  • 第68讲:MySQL触发器的核心概念以及常见的触发类型应用案例
  • VS Code 开发 Spring Boot 类型的项目
  • 数据中心加密:保障数据安全的重要一环
  • 分享90个节日庆典PPT,总有一款适合您
  • Python Faker批量生成测试数据
  • Docker-compose 运行MySQL 连接不上
  • Educational Codeforces Round 2 D 计算几何
  • hexo博客发布换电脑换地方了怎么办?
  • 最新知识付费变现小程序源码/独立后台知识付费小程序源码/修复登录接口
  • 奥威BI软件 | 职场人的数据可视化救星
  • 最长公共前缀[简单]
  • Java后端开发(十一)-- Mysql8的详细安装与环境配置
  • 什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
  • PyTorch 从tensor.grad 看 backward(权重参数) 和 gradient accumulated
  • fedora 命令行代理proxychains 使用flatpak下载 flathub包
  • 介绍kamailio的dialog模块
  • 性能优于BERT的FLAIR:一篇文章入门Flair模型
  • Weblogic ssrf漏洞复现
  • Memcached构建缓存服务器
  • vue3+element Plus实现弹框的拖拽、可点击底层页面功能
  • Vue+elementui 纯前端实现Excel导入导出功能(区分表头标题)
  • 使用Scrapy的调试工具和日志系统定位并解决爬虫问题
  • Pycharm安装配置Pyqt5教程(保姆级)
  • 基于单片机的养殖场温度控制系统设计
  • 时序分解 | Matlab实现EMD经验模态分解时间序列信号分解