大家好!我是曾续缘😛
今天是《LeetCode 热题 100》系列
发车第 73 天
栈第 5 题
❤️点赞 👍 收藏 ⭐再看,养成习惯
柱状图中最大的矩形 给定 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
解题方法
我们要求的是在一个由数字组成的柱状图中,能够找到的最大矩形的面积。这个矩形可以是水平也可以是垂直的。
首先,我们需要知道每个柱子左右两边第一个比它矮的柱子的位置。这样我们才能确定一个柱子能构成的所有可能的矩形。
如何找到柱子两边第一个比它矮的柱子位置呢?
我们利用单调栈找到每个柱子的左边界和右边界,将其存储在数组 l
和 r
中。
维护一个严格单调递增的栈,
- 当一个柱子可以入栈时,说明栈顶元素就是就是左边第一个比它矮的柱子位置。
- 当入了栈的柱子被当前柱子排出栈时,说明当前柱子是排出栈的柱子的第一个小于等于它的柱子,也就找到了排出栈柱子的右边第一个不比它高的柱子位置(因为有可能相等)。
- 使用右边不比它高的柱子来计算答案时不一定是最大的面积,但可以保证高度相等的最右侧柱子的答案是最大的。
得到数组 l
和 r
后,我们遍历每个柱子,用它的高度乘以它左右两边第一个比它矮的柱子之间的距离,这样就能得到以当前柱子为高的所有可能的矩形的面积。
最后,我们只需要在这些面积中找到最大的一个即可。
Code
class Solution {
// 寻找每个柱子左右两边第一个比它矮的柱子的位置
public int largestRectangleArea(int[] heights) {
int n = heights.length;
int[] l = new int[n], r = new int[n];
Arrays.fill(r, n);
Stack<Integer> stack = new Stack<Integer>();
for(int i = 0; i < n; i++){
// 当栈不为空,并且栈顶的柱子高度大于等于当前柱子的高度时
while(!stack.isEmpty() && heights[stack.peek()] >= heights[i]){
// 弹出栈顶元素,更新右边界
r[stack.pop()] = i;
}
// 如果栈为空,则当前柱子左边第一个比它矮的柱子是-1,否则就是栈顶元素
l[i] = stack.isEmpty() ? -1 : stack.peek();
// 把当前柱子压入栈
stack.push(i);
}
int ans = 0;
// 遍历每个柱子,计算以它为高的所有可能的矩形的面积
for(int i = 0; i < n; i++){
ans = Math.max(ans, heights[i] * (r[i] - l[i] - 1));
}
// 返回最大的矩形面积
return ans;
}
}