首先它是一个栈,即只能在栈顶插入和删除,其次它是单调的(单调递增or递减),所以插入元素A的时候,需要对比A和栈顶元素B,所有试图破坏这种单调性的元素都要被解决掉。
实际做题的时候,就是利用了这样的特点。
【题目类型总结】
在一维数组中找第一个满足XX条件的数
【题目1】
经典例题,给一个数组,返回一个大小相同的数组。返回的数组的第i个位置的值应当是,对于原数组中的第i个元素,至少往右走多少步,才能遇到一个比自己大的元素(如果之后没有比自己大的元素,或者已经是最后一个元素,则在返回数组的对应位置放上-1)。
简单的例子:
input: 5,3,1,2,4
return: -1 3 1 1 -1
【解析】
一般暴力解法就不说了。题目问往右走遇到一个最近的比自己大的,假设我从左往右遍历,右边的都是没有点亮的地图,一直往右,遇到每个索引,但是都不对(比自己小),我不知道至少找多久(最短距离)才能遇到那个比我大一点的,最差可能走到头也找不到(单身狗哭泣)。那么换一个思路,假设已婚的都是找到了正确的人的,那么他们回首往昔,啊,原来我们遇到的那天就是获得真爱的最短距离。这个比喻有点不恰当,将就看看吧。
那么新的思路出现了,我是一个指针i,从左往右走(遍历一维数组),检查数组i的值,能维持递减的就加到栈顶,如果想破坏这个单调性,就是要增,那么新元素A肯定比栈顶B大,那么,问题从往右至少多少步遇到一个大的,转换成了,往左至少多少步遇到一个小的。
你看,未来不知道(右边没有遍历过),历史却可查(左边的已经存好了),而且拿着新来的A跟栈顶B比较后,如果A>B,B就有了结果,B弹出来,A还是想入栈,就继续跟下一个栈顶元素B1比较,直到符合递减、A能入栈为止。
这就是利用了单调栈的特性,与其说是这种数据结构自身有什么好处,不如说解决问题时用这种思路比较巧妙。也注意到,栈顶元素总比栈底元素先找到结果,找到结果就走了,后进先出LIFO,这也符合栈的特征。
一般来说,处理一个一维数组,我们习惯从左往右遍历,如果一个元素老要跟前面一个元素对比,那么就适合用栈,插入删除的复杂度都是O(1),很方便,而且不用管前一个是什么i;如果类似上面这个题目,要跟前面n个元素对比大小,就用单调栈。
【小结】单调栈的性质
1.单调栈里的元素具有单调性,栈中元素只能是单调递增或者单调递减
2.元素加入栈前,会在栈顶端把破坏栈单调性的元素都删除;
3.使用单调栈可以找到元素向左遍历第一个比它小的元素,也可以找到元素向左遍历第一个比它大的元素。
(原文链接:https://blog.youkuaiyun.com/liujian20150808/article/details/50752861)
【题目2】
力扣739.每日温度
力扣https://leetcode.cn/problems/daily-temperatures/这个题目跟上面的谷歌算法题基本是一模一样了
【题目3】
这是一个困难题
84. 柱状图中最大的矩形https://leetcode.cn/problems/largest-rectangle-in-histogram/
【题目4】
这也是一个困难题