【算法】柱状图中最大的矩形

77 阅读2分钟

题目:柱状图中最大的矩形

难度:困难

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例:
示例1

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

示例2

输入:heights = [2,4]
输出:4
解释:最大的矩形为图中红色区域,面积为 4

提示:

1 <= heights.length <=105
0 <= heights[i] <= 104

1. 单调栈法(推荐,高效)

为什么想到用这种方法?
单调栈法之所以被想到,是因为它能够高效地处理当前柱子与其左右两边柱子高度的比较关系,利用栈的特性(后进先出)来快速确定每个柱子作为矩形高度时的左右边界。这种方法特别适合处理与顺序相关且需要快速检索“最近的特定条件”的问题。

具体步骤:

  • 初始化一个栈,栈中存放柱子的索引而非高度,栈底放置一个哨兵(索引为-1),用于简化边界处理。

  • 从左到右遍历柱状图数组,对于每个柱子,如果它比栈顶柱子高,直接入栈;如果它比栈顶柱子矮或等于,就不断弹出栈顶元素,计算以弹出柱子为高度、以其索引到当前柱子索引为宽度的矩形面积,并更新最大面积。

  • 遍历完成后,栈中剩余的柱子也要按照同样的逻辑处理,确保所有可能性都被考虑。

    function largestRectangleArea(heights) {
        let maxArea = 0;
        let stack = [-1]; // 哨兵,简化边界处理
        heights.push(0); // 保证最后所有元素出栈
    
        for (let i = 0; i < heights.length; i++) {
            // 当遇到比栈顶元素对应柱子矮的柱子时,计算栈顶元素对应的矩形面积
            while (heights[i] < heights[stack[stack.length - 1]]) {
                //stack.pop()得到stack数组中最后一个值,这意味着,stack删除了最后一项,长度为原来长度减1
                let height = heights[stack.pop()];
                // width中的stack是经过pop之后的值
                let width = i - stack[stack.length - 1] - 1;
                maxArea = Math.max(maxArea, height * width);
            }
            stack.push(i); // 当前柱子索引入栈
        }
    
        return maxArea;
    }