柱状图中最大的矩形——单调栈

70 阅读2分钟

image.png

代码:

  1. right,left,表示当前元素的右边第一个比它小的元素的下标和左边第一个比它小的元素的下标
  2. stk 用来维护元素单调递增的栈(模拟栈,模拟队列的一个数组切片)
  3. 初始化right
  4. 遍历he
  5. len(stk) > 0的时候且he[stk[len(stk)-1]] >= he[i],一直弹栈直到栈顶元素对应的值比当前元素小,或者len(stk) == 0,然后让这个比当前元素小的栈顶元素赋值给left就好了,最后记得将当前元素的下标压入栈中
  6. 我们每一次发现he[stk[len(stk)-1]] >= he[i]的时候,当前栈顶元素所对应的值就比现在的值大,那么我们就知道现在的栈顶元素的右边的第一个比它小的元素下标就是现在的元素的下标
  7. 在进行过这样的一个遍历之后,我们更新了每一个的left切片的值,但并没有更新每一个right的值,其实没有得到更新的right切片的哪些下标的值,说明这些下标的右边没有比它更小的值出现,那么这些值也就是我们在步骤3中所初始化的默认的n值
  8. 其中 left 中的 -1 的值就是下标 0 的左边的比它小的值的下标,
  9. right 中 n 自然就是下标 n-1 的右边比它小的值的下标
func largestRectangleArea(he []int) int {
    n := len(he)
    left, right := make([]int, n), make([]int, n)
    for i := 0; i < n; i++ {
        right[i] = n
    }
    stk := make([]int, 0)
    for i := 0; i < n; i++ {
        for len(stk) > 0 && he[stk[len(stk)-1]] >= he[i] {
            right[stk[len(stk)-1]] = i
            stk = stk[:len(stk)-1]
        }
        if len(stk) == 0 {
            left[i] = -1
        }else {
            left[i] = stk[len(stk)-1]
        }
        stk = append(stk, i)
    }
    ans := 0
    for i := 0; i < n; i++ {
        ans = max(ans, (right[i] - left[i] - 1) * he[i])
    }
    return ans
}

func max(x, y int) int {
    if x > y {
        return x
    }
    return y
}