算法题:柱状图中的最大矩形

300 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

大家好,这里依旧是人不狠,话也不多的我,文章尽量做到看过的都会

题目来自LeetCode.84. 柱状图中最大的矩形 leetcode.cn/problems/la…

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

Snipaste_2022-07-20_22-55-21.png

数据结构:栈

栈:一种线性数据结构,后进先出,只有一端(栈顶)可以任意进出元素

单调栈:顾名思义,具有单调性的栈,分为单调递增和单调递减,本题使用单调递增栈

思路简介:求出所有高度情况下的最大宽度。我们遍历每一个柱子,若高于栈顶柱子的高度,则将该柱子入栈。如果当前柱子高度小于栈顶高度,说明以栈顶高度为高的矩形,最大宽度可以得知,便可求出此时面积s,并且将栈顶柱子删除。

开始理解以下几点:

1.因为我们维持的是一个单调递增栈,所以数组中每一个给定高度的元素的最大宽度可以获得。

2.所以当入栈元素进栈时,栈内值大于入栈元素的会出栈,我们在此时计算出栈元素的宽度以及高度

例如:当栈内元素[1,5,6]时 ,下一个元素 2 要入栈, 2 < 6 ,所以我们删除 6 
此时高度为 6 的矩形,最大宽度width = 12的索引 - 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
};