LeetCode-84. 柱状图中最大的矩形【栈 数组 单调栈】

发布于:2024-04-08 ⋅ 阅读:(116) ⋅ 点赞:(0)

LeetCode-84. 柱状图中最大的矩形【栈 数组 单调栈】

题目描述:

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例 1:
在这里插入图片描述
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
示例 2:
在这里插入图片描述
输入: heights = [2,4]
输出: 4

提示:

1 <= heights.length <=105
0 <= heights[i] <= 104

解题思路一:单调栈

  1. 柱状图前后加0
  2. 维护一个从栈底到栈顶的单调增栈。【栈顶大于前一个元素】,那么获取到
    主要就是分析清楚如下三种情况:

情况一:当前遍历的元素heights[i]大于栈顶元素heights[st.top()]的情况【进栈】
情况二:当前遍历的元素heights[i]等于栈顶元素heights[st.top()]的情况【可忽略】
情况三:当前遍历的元素heights[i]小于栈顶元素heights[st.top()]的情况【计算当前ans=(i - stack[-1] - 1) * heights[stack[-1]】

我在 height数组上后,都加了一个元素0, 为什么这么做呢?

首先来说末尾为什么要加元素0?

如果数组本身就是升序的,例如[2,4,6,8],那么入栈之后 都是单调递减,一直都没有走 情况三 计算结果的哪一步,所以最后输出的就是0了。 如图:
在这里插入图片描述
那么结尾加一个0,就会让栈里的所有元素,走到情况三的逻辑。

开头为什么要加元素0?

如果数组本身是降序的,例如 [8,6,4,2],在 8 入栈后,6 开始与8 进行比较,此时我们得到 mid(8),rigt(6),但是得不到 left。

(mid、left,right 都是对应版本一里的逻辑)

因为 将 8 弹出之后,栈里没有元素了,那么为了避免空栈取值,直接跳过了计算结果的逻辑。

之后又将6 加入栈(此时8已经弹出了),然后 就是 4 与 栈口元素 8 进行比较,周而复始,那么计算的最后结果resutl就是0。 如图所示:
在这里插入图片描述

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        heights.insert(0, 0)
        heights.append(0)
        stack = [0]
        result = 0
        for i in range(1, len(heights)):
            if heights[i] > heights[stack[-1]]:
                stack.append(i)
            elif heights[i] == heights[stack[-1]]:
                stack.pop()
                stack.append(i)
            else:
                while stack and heights[i] < heights[stack[-1]]:
                    mid_index = stack[-1]
                    stack.pop()
                    if stack:
                        w = i - stack[-1] - 1
                        result = max(result, w * heights[mid_index])
                stack.append(i)
        return result

时间复杂度:O(n)
空间复杂度:O(n)

解题思路二:


时间复杂度:O(n)
空间复杂度:O(n)

解题思路三:


时间复杂度:O(n)
空间复杂度:O(n)