73.柱状图中最大的矩形(学习)
给定 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.stack是一个空栈,用于存储柱子的索引。
2.maxArea用于记录遍历过程中找到的最大矩形面积。
3.在heights数组末尾添加一个高度为0的柱子是为了确保栈中所有元素都能被处理。因为当遍历到数组末尾时,栈中可能还剩余一些索引,这些索引对应的柱子右边没有比它们矮的柱子,通过添加一个高度为0的柱子,我们可以确保这些索引也能被弹出并计算面积。
二、遍历数组
我们遍历heights数组中的每个索引i。
处理栈和计算面积
1.在遍历过程中,对于每个索引i,我们执行以下操作:
1.1.弹出栈顶元素:只要栈不为空且当前柱子的高度小于栈顶索引对应的柱子高度,就不断弹出栈顶索引。对于每个弹出的栈顶索引top,我们可以计算以heights[top]为高的矩形的宽度,这个宽度是当前索引i(或数组末尾添加的0的索引)与栈中新的栈顶索引之间的距离减1(因为我们要排除新的栈顶索引对应的柱子)。然后,我们计算面积(高度乘以宽度),并与maxArea比较,更新maxArea(如果需要)。
1.2.将当前索引压入栈中:将当前索引i压入栈中,以便后续可能的比较。
三、结束遍历
1.当遍历完整个heights数组后,栈中可能还剩余一些索引,这些索引对应的柱子右边没有比它们矮的柱子(但由于我们在数组末尾添加了一个高度为0的柱子,所以这些索引现在都能被处理)。随着遍历的继续(实际上是由于我们在数组末尾添加了一个0,所以循环会多执行一次),这些索引会被弹出并计算面积。
四、返回结果
1.最后,函数返回maxArea,即能够勾勒出的最大矩形面积。
var largestRectangleArea = function (heights) {
let stack = []; // 存储索引的栈
let maxArea = 0;
heights.push(0); // 添加一个高度为0的柱子,用于处理栈中剩余的元素
for (let i = 0; i < heights.length; i++) {
while (stack.length > 0 && heights[i] < heights[stack[stack.length - 1]]) {
let height = heights[stack.pop()];
let width;
if (stack.length === 0) {
// 栈为空,说明当前柱子左边没有比它矮的柱子
width = i;
} else {
// 否则,宽度为当前索引与栈顶索引之间的距离
width = i - stack[stack.length - 1] - 1;
}
maxArea = Math.max(maxArea, height * width);
}
stack.push(i);
}
return maxArea;
};