目录

单调栈

做完题后喜欢看看别人的思路,总能发现不一样的方法,让人直呼🤙🤙🤙

在用递归做完最大二叉树后,也是看到别人用单调栈的方法,发现很巧妙,想着深入学习一下~

什么是单调栈

单调栈指的是:栈中存放的数据出栈应该是有序的

单调递增栈:栈中数据出栈的序列为单调递增序列(栈顶到栈底–>递增)

单调递减栈:栈中数据出栈的序列为单调递减序列(栈顶到栈底–>递减)

栈结构大家都很熟悉(先进后出),那单调栈到底有啥用呢?

单调栈主要回答这样的几种问题:

  • 比当前元素更大的下一个元素
  • 比当前元素更大的前一个元素
  • 比当前元素更小的下一个元素
  • 比当前元素更小的前一个元素

废话不多说,还是直接用代码解释更简单明了……

更大的下一个

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def nextGreaterElement(self, nums):
        '''
        res:'-1'代表没有大于当前元素的值,其他值代表大于当前值的下一个值,下同
        '''
        stack = list()
        res = [-1] * len(nums)
        for i, n in enumerate(nums):
            # 入栈元素只能比栈顶元素小,新元素大于栈顶,就要更新
            while stack and nums[stack[-1]] < n:
                # 这一步执行具体的操作,这里是记录下一个大的数
                res[stack.pop()] = n
            stack.append(i)
        return res

更大的前一个

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def preGreaterElement(self, nums):
        stack = list()
        res = [-1] * len(nums)
        for i, n in enumerate(nums):
            # 保证先进栈的元素大,如果来个更大的,就把前面小的全部pop掉,保证站内元素是紧密相连的有序序列
            while stack and nums[stack[-1]] < n:
                stack.pop()
            if stack:
                res[i] = nums[stack[-1]]
            stack.append(i)
        return res

更小的下一个

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def nextSmallerElement(self, nums):
        stack = list()
        res = [-1] * len(nums)
        for i, n in enumerate(nums):
            # 入栈元素只能比栈顶元素大
            while stack and nums[stack[-1]] > n:
                # 这一步执行具体的操作,这里是记录下一个小的数
                res[stack.pop()] = n
            stack.append(i)
        return res

更小的前一个

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def preSmallerElement(self, nums):
        stack = list()
        res = [-1] * len(nums)
        for i, n in enumerate(nums):
            # 保证先进栈的元素小
            while stack and nums[stack[-1]] > n:
                stack.pop()
            if stack:
                res[i] = nums[stack[-1]]
            stack.append(i)
        return res

总结:单调栈就是维护一个栈内数据有序的栈,只要栈内元素不是单调的,就一个个把栈顶元素pop掉,直到新加入的元素和剩余的元素单调为止。在pop操作的同时,更新具体需求的操作就行。具体的实例有很多,可以查看上一篇文章最大二叉树的单调栈解法。