题目 84. 柱状图中最大的矩形
思路
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
方法1 双指针
最大面积等于遍历每一个柱子,包含当前柱子形成的矩形的最大面积。计算每一个柱子左侧比它小的index,右侧比它小的index,然后再遍历,每个的面积等于当前柱子的高度 * (右侧-左侧-1),取最大值。
/**
* @param {number[]} heights
* @return {number}
*/
var largestRectangleArea = function(heights) {
const len = heights.length;
const minLeftArr = new Array(len);
const minRightArr = new Array(len);
minLeftArr[0] = -1;
for (let i = 1; i < len; i++) {
let j = i - 1;
while(j >= 0 && heights[j] >= heights[i]) {
j = minLeftArr[j];
}
minLeftArr[i] = j;
}
minRightArr[len-1] = len;
for (let i = len - 2; i >= 0; i--) {
let j = i + 1;
while(j < len && heights[j] >= heights[i]) {
j = minRightArr[j];
}
minRightArr[i] = j;
}
let result = 0;
for (let i = 0; i < len; i++) {
const sum = heights[i] * (minRightArr[i] - minLeftArr[i] - 1);
result = Math.max(sum, result);
}
return result;
};
方法2 单调栈
和接雨水题目类似,但是栈是从大到小的。
- 如果元素大于栈顶元素,则入栈
- 元素等于栈顶元素,栈顶元素先出栈,再入栈当前元素
- 元素小于栈顶元素,则开始计算,执行while循环,每次计算当前栈顶元素的最大矩形,出栈该元素,直到遇到大于栈顶的元素,将该元素入栈。
兼容递增或者递减的序列,将height前后插入0形成新的数组
var largestRectangleArea = function(heights) {
heights = [0, ...heights, 0];
const len = heights.length;
const stack = [];
stack.push(0);
let result = 0;
for (let i = 1; i < len; i++) {
const val = heights[i];
let topIndex = stack[stack.length - 1];
let top = heights[topIndex];
if (val >= top) {
stack.push(i);
} else {
while (stack.length && val < heights[topIndex]) {
const midIndex = stack.pop();
if (stack.length) {
const left = stack[stack.length - 1];
const right = i;
const w = right - left - 1;
const h = heights[midIndex];
result = Math.max(result, w * h);
topIndex = left;
}
}
stack.push(i);
}
}
return result;
}