柱状图中最大的矩形-leetcode
题目描述
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 1:

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

输入: heights = [2,4]
输出: 4
提示:
1 <= heights.length <=1050 <= heights[i] <= 104
解法一
思路:
- 核心思想
我们要找到一个矩形,它的高度由某一个柱子 ii 的高度 heights[i] 决定。那么,这个矩形能向左右延伸多远呢?
- 左边界:左边第一个比
heights[i]矮的柱子。 - 右边界:右边第一个比
heights[i]矮的柱子。
一旦确定了左右边界,以 heights[i] 为高的矩形面积就是:
extArea=extheights[i]imes(ext右边界索引−ext左边界索引−1)extArea=extheights[i]imes(ext右边界索引−ext左边界索引−1)
- 为什么用单调栈?
单调栈可以帮助我们在一次遍历中,为每个柱子找到左右两边最近的比它矮的柱子。
- 我们维持一个从栈底到栈顶单调递增的栈(存储柱子的下标)。
- 当我们遇到一个比栈顶元素矮的柱子时,说明找到了栈顶元素的“右边界”。
- 而栈顶元素在栈中的前一个元素,就是它的“左边界”。
- 算法步骤
为了处理边界情况(例如所有柱子都是递增的,或者栈中最后剩下的元素),我们通常在原数组的开头和结尾各加一个高度为 0 的“哨兵”柱子。
- 在
heights数组前后各加一个0。 - 初始化一个空栈,先压入第一个哨兵(索引 0)。
- 从索引 1 开始遍历数组:
- 如果当前柱子高度 大于等于 栈顶柱子高度:将当前索引入栈(保持单调递增)。
- 如果当前柱子高度 小于 栈顶柱子高度:说明栈顶柱子的右边界找到了。
- 弹出栈顶元素,记为
mid,其高度为h = heights[mid]。 - 新的栈顶元素就是
mid的左边界,记为left = stack.top()。 - 当前遍历到的索引就是
mid的右边界,记为right = i。 - 计算面积:
width = right - left - 1,area = h * width。 - 更新最大面积。
- 重复此过程,直到当前柱子不再小于栈顶柱子,然后将当前索引入栈。
- 弹出栈顶元素,记为
代码:
public class Solution {
public int largestRectangleArea(int[] heights) {
// 1. 处理边界情况
if (heights == null || heights.length == 0) {
return 0;
}
// 2. 准备一个新的数组,首尾各加一个高度为 0 的“哨兵”
// 哨兵的作用:
// 左侧 0:保证第一个柱子入栈时,栈不为空,且左边界能被正确计算
// 右侧 0:保证遍历结束时,栈内所有剩余的柱子都能被弹出并计算面积
int[] newHeights = new int[heights.length + 2];
newHeights[0] = 0;
for (int i = 0; i < heights.length; i++) {
newHeights[i + 1] = heights[i];
}
newHeights[newHeights.length - 1] = 0;
// 3. 定义单调递增栈(存储的是索引)
Deque<Integer> stack = new ArrayDeque<>();
int maxArea = 0;
// 4. 开始遍历
for (int i = 0; i < newHeights.length; i++) {
// 如果当前柱子高度小于栈顶柱子高度,说明栈顶柱子的右边界找到了
while (!stack.isEmpty() && newHeights[i] < newHeights[stack.peek()]) {
// 弹出栈顶元素作为待计算矩形的高度
int midIndex = stack.pop();
int h = newHeights[midIndex];
// 此时新的栈顶元素就是该柱子的左边界索引
// 右边界索引就是当前的 i
int leftIndex = stack.peek();
int rightIndex = i;
// 宽度 = 右边界 - 左边界 - 1
int w = rightIndex - leftIndex - 1;
// 更新最大面积
maxArea = Math.max(maxArea, h * w);
}
// 当前索引入栈,保持栈内高度单调递增
stack.push(i);
}
return maxArea;
}
}

浙公网安备 33010602011771号