系列文章导引

  • 系列文章导引

开源项目

本系列所有文章都将会收录到GitHub中统一收藏与管理,欢迎ISSUEStar

GitHub传送门:Kiner算法算题记

知识回顾

我们之前讨论过单调队列,知道单调队列是用来维护区间最值的神兵利器:维护区间最小值用单调递增队列,维护区间最大值用单调递减队列。

单调队列有两种操作:

入队操作:从尾部入队,入队时,为了保证队列的单调性,需要将队列中已有所有违反单调性的元素都删掉之后再将新元素入队

出队操作:当头部元素已经移出了滑动窗口时,需要将头部元素从头部出队。

那么,大家再来思考一件事,我们的队列和栈有啥关系吗?我们是不是可以把栈看成是一头被堵住的队列呢?由于便秘屁股被堵住了出不去,所以这哥们只能通过抠喉把吃进去的东西吐出来才能好受一点,这就是我们的。虽然这个比喻略显粗鄙,但还是很说明问题的。一语中的的道出栈的特点:从顶部入队,也从顶部出队,后进先出

其实,我们今天要讨论的单调栈,就可以看成把屁股堵住的单调队列

单调栈的特性(渣男本质)

如果你是一个情场老手,或许有这样一个感受:所有被我追到的女生,我在她们心里就是“男神”。而那些我追不到的女生,在我心里都是我的“女神”。所谓“得不到的永远在骚动,被偏爱的有恃无恐”。可见,很多男生反而是对那些很难追到手的女生念念不忘,而对于轻易到手的女生则是没那么上心,也就是我们常说的“渣男”。而我们今天要聊的单调栈,就是数据结构中的“渣男”。

在我们的单调栈中,所有在入栈时被“我”忽悠出去到处浪的“女生”(因违反单调性出栈的元素),我都是她们的“男神”,由于太轻易得手,反而不知道珍惜。而那个永远对我爱答不理,怎么忽悠都不动如风的女神(第一个不违反单调性的元素),我总是无可奈何却又念念不忘。

单调递增栈

此时,我们的单调栈是个“御姐控”,喜欢比自己大的,所有比自己小的小妹妹们都只能感叹“君生妾未生,妾生君已老”。

出栈的元素都比当前要入栈的元素小,即入栈元素是第一个比这些出栈元素小的元素。

利用单调递增栈,可以维护任意一个元素最近的比他小的元素,即维护元素最近小于关系

单调递减栈

此时,我们的单调栈是个“萝莉控”,喜欢比自己小的,所有比自己大的姐姐们都只能感叹“妾生君未生,君生妾已老”。

出栈的元素都比当前要入栈的元素大,即入栈元素是第一个比这些出栈元素大的元素。

利用单调递减栈,可以维护任意一个元素最近的比他大的元素,即维护元素最近大于关系

单调栈的代码实现

# 单调递增栈
idx:     0  1  2  3  4  5  6  7  8  9┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
stack:    6  7  9                          <━ 0┗━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┛
val:     6  7  9  0  8  3  4  5  1  2  # 如上图,当0要入栈时,由于前面的6、7、9都违反了单调性,将他们依次弹出为[9,7,6],而0就是9最近的小于9的元素,也就是当前元素上一个最近的比自己大的元素就是栈顶元素
interface Res {stack: number[],prev: number[],next: number[]
}
// 查找数组中每个数最近的小于这个数的索引
function main(arr: number[]): Res {// 维护小于关系,用单调递增栈const stack: number[] = [];const prev: number[] = new Array(arr.length);const next: number[] = new Array(arr.length);for(let i=0;i<arr.length;i++) {// 将元素压入单调栈之前,先检查一下待压入元素是否小于栈顶元素,因为我们要找最近小于目标元素的索引,因此,我们需要一个// 单调递增的栈,因此,只要待压入元素小于栈顶元素,我们就要把栈顶元素弹出,以此来维护栈的单调性// 弹出后,将弹出元素所对应的索引与当前元素关联,即代表该元素是距离当前元素最近的一个大于当前元素的数,// 换句话来说,就是距离stack.pop()所在位置元素最近的小于这个元素的位置是i,也就是,栈顶元素后面最近的小于栈顶的元素就是i所在的元素while(stack.length && arr[i] < arr[stack[stack.length-1]]) {next[stack.pop()] = i;}// 如果栈为空,那么上一个元素是不存在的,所以是-1if(stack.length === 0) prev[i] = -1;// 否则当前元素上一个小于他的元素就是栈顶元素,即当前元素前面最近的比当前元素大的元素就是栈顶元素else prev[i] = stack[stack.length - 1];stack.push(i);}// 如果上面的循环结束,栈中仍然存在元素,那么其实是不可能存在下一个元素,我们把栈中剩余的所有元素弹出,并将该元素对应的下个元素的所以设置为数组长度while(stack.length) next[stack.pop()] = arr.length;return {stack,prev,next}
}const arr = [6,7,9,0,8,3,4,5,1,2];
const res: Res = main(arr);console.log(`indx:\t ${arr.map((item, idx) => idx).join('\t')}`);
console.log(`curr:\t ${arr.join('\t')}`);
console.log(`prev:\t ${res.prev.join('\t')}`);
console.log(`next:\t ${res.next.join('\t')}`);// indx:    0      1       2       3       4       5       6       7       8       9
// curr:    6      7       9       0       8       3       4       5       1       2
// prev:    -1     0       1       -1      3       3       5       6       3       8
// next:    3      3       3       10      5       8       8       8       10      10

Kiner算法刷题记(十四):数据结构中的“渣男”——单调栈(数据结构基础篇)相关推荐

  1. Kiner算法刷题记(二十一):字典树与双数组字典树(数据结构基础篇)

    字典树与双数组字典树(数据结构基础篇) 系列文章导引 系列文章导引 开源项目 本系列所有文章都将会收录到GitHub中统一收藏与管理,欢迎ISSUE和Star. GitHub传送门:Kiner算法算题 ...

  2. 7月算法训练------第十四天(栈)解题报告

    7月算法训练------第十四天(栈)解题报告 题目类型:栈 题目难度:简单 第一题.1614. 括号的最大嵌套深度 题目链接:1614. 括号的最大嵌套深度 思路分析: 遍历整个字符串,如果是'(' ...

  3. 算法系列之十四:狼、羊、菜和农夫过河问题

    算法系列之十四:狼.羊.菜和农夫过河问题 题目描述:农夫需要把狼.羊.菜和自己运到河对岸去,只有农夫能够划船,而且船比较小,除农夫之外每次只能运一种东西,还有一个棘手问题,就是如果没有农夫看着,羊会偷 ...

  4. 【Java数据结构与算法】第十四章 红黑树

    第十四章 红黑树 文章目录 第十四章 红黑树 一.红黑树 1.介绍 2.插入结点 3.删除结点 4.与平衡二叉树的对比 一.红黑树 1.介绍 红黑树(Red Black Tree)是平衡二叉树的其中一 ...

  5. 机器学习算法(二十四):最近邻算法 KNN(k-nearest neighbor)

    目录 1 基于实例的学习 2 k-最近邻法 2.1 算法概述 2.2 kNN算法的一般流程 2.3 距离公式 2.4 k值的选择 2.5 KNN特点 2.5.1 特点 2.5.2 KNN算法的优势和劣 ...

  6. 第十二届_国赛蓝桥杯个人模板_基础篇

    第十二届_国赛蓝桥杯个人模板_网格图_DFS/BFS篇 第十二届_国赛蓝桥杯个人模板_全排列_DFS/BFS篇 第十二届_国赛蓝桥杯个人模板_DP篇 第十二届_国赛蓝桥杯个人模板_数论篇 第十二届_国 ...

  7. 经典算法题:字典树、并查集、单调栈、二分、带标记函数dp、树、全排列、字符串问题等常用算法

    0. Tips 1. 位运算 如何枚举一个二进制状态数字k的子集, 方法就是针对中的二进制为1的位开始进行减法,判断数字k的二进制子集, 像枚举(2^k-1) ~ 0一样枚举其子集: int sub ...

  8. 【数据分析师---数据可视化】第二章:plotly绘图基础篇

    plotly绘图基础篇 1 Plotly简介与安装 2 Plotly简单绘图入门 3 Plotly绘制散点图和饼图 4 Plotly绘图流程详细梳理 5 Plotly绘制密度图和三维散点图 5.1 绘 ...

  9. 机器学习算法系列(十四)-硬间隔支持向量机算法(Hard-margin Support Vector Machine)

    阅读本文需要的背景知识点:拉格朗日乘子法.KKT条件.一丢丢编程知识 一.引言   前面一节我们介绍了一种分类算法--朴素贝叶斯分类器算法,从概率分布的角度进行分类.下面我们会花几节来介绍另一种在分类 ...

最新文章

  1. 中文TTS文字转语音合成模块合成成品带喇叭 替代SYN6288和XFS5152
  2. matlab im2double
  3. 文件系统:隐匿在 Linux 背后的机制
  4. 计算机基础的算法思想
  5. 商超小程序服务器配置,超市商超小程序在线开店的教程
  6. IDEA和MySQL数据库建立连接
  7. sql插入多条记录_如何在SQL中插入多条记录
  8. android静态库动态库,Android 动态库和静态库
  9. maxlength中文和英文html,让input maxlength区分中英文
  10. 【今日学长】来自柚子帮学长--英国留学租房攻略!
  11. 如何在linux系统上添加网口打印机
  12. 软件与证书之间的关系
  13. 根据屏幕大小动态设置字体rem
  14. 【建议收藏】ChatGPT 联网版抢先体验,学会这 8 大高阶实用技巧,让你秒上手!
  15. word文件取消只读模式
  16. push to origin/dev was rejected
  17. 中国各省份省会地图json数据
  18. java图片去掉文字_java解出图片中的文字
  19. (静态,动态,文件)三个版本的通讯录
  20. Python turtle 画正多边形和多角形

热门文章

  1. JLINK V10 Keil5.28使用处理
  2. 二极管的分类以及应用
  3. 微纳米气泡机​电镀工业园区(厂)污水处理整体解决方案
  4. 【优达学城测评】机器学习工程师纳米学位的学习体验
  5. 应用场景四:西门子PLC连接ModbusRTU从站设备解决方案
  6. python 用geopandas,rasterio,gdal完成arcgis分区统计功能(zonal)
  7. SHELL脚本之统计目录下文件及子目录数量
  8. jieba库、wordcloud库
  9. Tomcat在eclipse中的配置及Lomboz(J2EE如web services、web and XML、Strust等组件)的配置
  10. python3字典列表_Python3 列表、元组、字典