单调栈

由于有四种情况的单调栈,为了不容易出错,我决定全部转换成「求左边第一个比自己小的」单调栈

0X00 模板

求左边第一个比自己小的 模板

def make(a):
    n = len(a)
    ans = [float("inf")] * n
    stack = []
    for i, v in enumerate(a):
        while stack and stack[-1] >= v: stack.pop()
        if stack: ans[i] = stack[-1]
        stack.append(v)
    return ans
  • 如果求左边第一个比自己大的,就把原数组取负
  • 如果求右边第一个比自己小的,就把原数组取反,最后一定要思考是不是要反过来
  • 如果求右边第一个比自己大的,就把原数组取反,再全部取负数,最后也一定要思考是不是要反过来

0X01 引申

求左边比自己大的里面最小的

我们把原数组的下标按照值按降序排序,然后左边第一个下标比自己小的就是「左边比自己大的里面最小的」

975. 奇偶跳

class Solution:
    def oddEvenJumps(self, A: List[int]) -> int:
        def make(a):
            stack, res = [], [None] * n
            for _, v in enumerate(a):
                while stack and stack[-1] > v: stack.pop()
                if stack: res[v] = stack[-1]
                stack.append(v)
            return res
        
        n, A = len(A), A[::-1]
        B = sorted(range(n), key=lambda i: -A[i])
        oddprev = make(B)
        B = sorted(range(n), key=lambda i: A[i])
        evenprev = make(B)
        odd, even = [False] * n, [False] * n
        odd[0] = even[0] = True
        for i in range(1, n):
            if oddprev[i] != None:
                odd[i] = even[oddprev[i]]
            if evenprev[i] != None:
                even[i] = odd[evenprev[i]]

        return sum(odd)

求左边比自己小的最大的

把原数组的下标按升序排序,然后左边第一个下标比自己小的就是「左边比自己小的最大的」

0X02 相关题目

注意判断尽量使用 != None

  • 84. Largest Rectangle in Histogram
  • 85. Maximal Rectangle
  • 739. Daily Temperatures
  • 503. Next Greater Element II

你可能感兴趣的:(单调栈)