本文已参与「新人创作礼」活动,一起开启掘金创作之路。
大家好,这里依旧是人不狠,话也不多的我,文章尽量做到看过的都会
题目来自LeetCode.84. 柱状图中最大的矩形 leetcode.cn/problems/la…
题目:给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
数据结构:栈
栈:一种线性数据结构,后进先出,只有一端(栈顶)可以任意进出元素
单调栈:顾名思义,具有单调性的栈,分为单调递增和单调递减,本题使用单调递增栈
思路简介:求出所有高度情况下的最大宽度。我们遍历每一个柱子,若高于栈顶柱子的高度,则将该柱子入栈。如果当前柱子高度小于栈顶高度,说明以栈顶高度为高的矩形,最大宽度可以得知,便可求出此时面积s,并且将栈顶柱子删除。
开始理解以下几点:
1.因为我们维持的是一个单调递增栈,所以数组中每一个给定高度的元素的最大宽度可以获得。
2.所以当入栈元素进栈时,栈内值大于入栈元素的会出栈,我们在此时计算出栈元素的宽度以及高度
例如:当栈内元素[1,5,6]时 ,下一个元素 2 要入栈, 2 < 6 ,所以我们删除 6
此时高度为 6 的矩形,最大宽度width = 1 (2的索引 - 5的索引 -1) 高度6的矩形面积 = 6*width
3.当我们依次遍历完数组,将栈内剩余所有元素依次出栈,依次计算面积。
代码
var largestRectangleArea = function (heights) {
let max = 0
//初始化单调栈,存入索引和高度
let stack = [{ index: -1, height: -1 }]
//遍历数组元素,依次入栈出栈
for (let i = 0; i < heights.length; i++) {
//当栈顶索引不为-1 并且 入栈元素高度小于栈顶元素高度,删除栈顶元素
while (stack[stack.length - 1].index != -1 && stack[stack.length - 1].height > heights[i]) {
let pop = stack.pop()
//计算以出栈元素的height为高的矩形的最大面积,赋值给max
max = Math.max(max, pop.height * (i - 1 - stack[stack.length - 1].index))
}
//确定高度大于栈顶元素后,元素入栈,存入索引和高度
stack.push({ index: i, height: heights[i] })
}
//循环结束后,单调递增栈的元素的宽度均为栈顶的索引-各元素的索引
let right = stack[stack.length - 1].index
//当遍历结束,栈不为空时,将剩下元素依次出栈并计算面积
while (stack[stack.length - 1].index != -1) {
let pop = stack.pop()
//求栈内剩下柱子的面积,赋值给max
max = Math.max(max, (right - stack[stack.length - 1].index) * pop.height)
}
return max
};