Skip to content

Latest commit

 

History

History
98 lines (57 loc) · 3.77 KB

单调栈.md

File metadata and controls

98 lines (57 loc) · 3.77 KB

单调栈

单调栈是什么?

如名,就是在栈中的元素是有序的,故可以分为 单调递增栈 和 单调递减栈 (注意是按照出栈之后的顺序来说的)

  1. 单调递增栈:栈中数据出栈的序列为单调递增序列
  2. 单调递减栈:栈中数据出栈的序列为单调递减序列

牢记栈中数据永远是有序的

主要解决问题

只处理一种典型的问题,叫做 Next Greater Element, 即寻找一侧第一个大于(或者小于)的边界

单调栈专门处理类似「找右边第 1 个大于自己的元素」的问题的

原因:

  • 我们只关心那个最近的问题,后进先出,符合栈的使用场景;
  • 又有大小关系,因此栈中每时每刻的形态就是「单调」的。

模拟单调栈的数据push和pop

模拟实现一个递增单调栈:

现在有一组数10,3,7,4,12。从左到右依次入栈,则如果栈为空或入栈元素值小于栈顶元素值,则入栈;否则,如果入栈则会破坏栈的单调性,则需要把比入栈元素小的元素全部出栈。单调递减的栈反之。

  • 10入栈时,栈为空,直接入栈,栈内元素为10。

  • 3入栈时,栈顶元素10比3大,则入栈,栈内元素为10,3。

  • 7入栈时,栈顶元素3比7小,则栈顶元素出栈,此时栈顶元素为10,比7大,则7入栈,栈内元素为10,7。

  • 4入栈时,栈顶元素7比4大,则入栈,栈内元素为10,7,4。

  • 12入栈时,栈顶元素4比12小,4出栈,此时栈顶元素为7,仍比12小,栈顶元素7继续出栈,此时栈顶元素为10,仍比12小,10出栈,此时栈为空,12入栈,栈内元素为12。

即: 判断是递增还是递减栈 递增 则出栈是递增 栈内应该是递减 小于则入栈

  1. 栈为空或当前元素值小于栈顶元素值,则入栈
  2. 当前元素值大于栈顶元素,则将栈顶元素出栈,直到栈顶元素大于当前元素值 此时再入栈

例题

具体查看代码注释

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        if not heights:
            return 0

        # 使用单调栈 什么是单调栈? 需要的是两边的边界》= 当前的值 即栈内单调递增 即 单调递减栈
        # 增加两个哨兵节点 减少非空判断 
        size = len(heights)
        res = 0
        heights = [0] + heights + [0]
        stack = [0]
        size += 2 

        # 第一个的判断呢? 
        for i in range(1, size):
            while heights[i] < heights[stack[-1]]:
                # 找到一个小于的元素了 那么开始可以更新答案 
                # 这是本轮次可以计算的 底的下标  即以 heights[top] 为底 同时i为右边界 此时的左边界呢? 注意栈顶是 stack【-1】 
                # 此时的左边界 因为是单调递减栈  栈内是单调递增的 top出栈之后的下一个就是小于top元素的下标 即左边界确定
                # 在这次的while 循环中 
                cur_height = heights[stack[-1]] 
                stack.pop()
                # cur_height = heights[stack.pop()]
                cur_width = i - stack[-1] -1 
                print(cur_height, cur_width)
                res = max(res, cur_height*cur_width)
            
            # 栈内没有比当前索引处高度小的了,将当前索引进栈 上面是while循环 把大于当前值的全部排出 
            stack.append(i)
        
        return res 

和单调栈有关的4道题目以及解析

https://leetcode-cn.com/problems/remove-duplicate-letters/solution/yi-zhao-chi-bian-li-kou-si-dao-ti-ma-ma-zai-ye-b-4/