84. 柱状图中最大的矩形

目录:

题目

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

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

示例 1:

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

示例 2:

输入: heights = [2,4]
输出: 4

提示:

  • 1 <= heights.length <=10^5
  • 0 <= heights[i] <= 10^4

 暴力法

  • 我们可以遍历每根柱子,以当前柱子 i 的高度作为矩形的高,
  • 那么矩形的宽度边界即为向左找到第一个高度小于当前柱体 i 的柱体,向右找到第一个高度小于当前柱体 i 的柱体。
  • 对于每个柱子我们都如上计算一遍以当前柱子作为高的矩形面积,最终比较出最大的矩形面积即可。
class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        if(n==0)return 0;
        int ret = 0;
        for(int i = 0;i<n;i++)
        {
            int width = 1;
            int left = i-1;
            while(left>=0 && heights[left]>=heights[i])
            {
                width++;
                left--;
            }
            int right = i+1;
            while(right<n && heights[right]>=heights[i])
            {
                width++;
                right++;
            }
            if(width*heights[i]>ret)ret = width*heights[i];

        }
        return ret;

    }

}

单调栈法

  • 本质还是枚举以每一个柱体i的高度为矩形的高,向左、向右所能构成的最大的矩形宽度
  • 暴力法寻找左边界需要$o(N)$,而借助于非递减单调栈,对于栈中的每一个元素,它的左边界是它的栈中的下一个元素

因此做法就很简单了,

  • 我们遍历每个柱体,若当前的柱体高度大于等于栈顶柱体的高度,说明栈顶柱体还没有达到右边界,就直接将当前柱体入栈,
  • 否则若当前的柱体高度小于栈顶柱体的高度,说明当前栈顶柱体找到了右边的第一个小于自身的柱体,那么就可以将栈顶柱体出栈来计算以其为高的矩形的面积了

最后若栈中还有元素,则根据我们的过程,

  • 栈中每个元素的左边界为它在栈中的下一个柱体,
  • 由于这个元素还在栈中,所以它的右边界还没找到才仍然留在了栈中(若找到了就出栈了),留在栈中的都是右边界还没有找到的,所以计算以它为高度的最大矩形时,最右边界是n,
  • 所有不在栈中的元素都是已经被消掉的,因为它的左右边界都是已经找到的了,已经是确定的了,已经没有利用价值了,所以才被消掉
class Solution {
    public int largestRectangleArea(int[] heights) { 
        
        Deque<Integer> stk = new ArrayDeque<>();
        int area = 0,n = heights.length;
        for(int i = 0; i < n; ++i) {
            while(!stk.isEmpty() && heights[i] < heights[stk.peek()]) {
                int h = heights[stk.peek()];
                stk.pop();
                int w = stk.isEmpty() ? i : i-1-stk.peek();
                area = Math.max(h * w, area);
            }
           
            stk.push(i);
        }

        while(!stk.isEmpty()) {
            int h = heights[stk.peek()];
            stk.pop();
            int w = stk.isEmpty() ? n : n-1-stk.peek();
            area = Math.max(h * w, area);
        }

        return area;

    }
}

   

posted on 2022-06-04 13:44  朴素贝叶斯  阅读(64)  评论(0编辑  收藏  举报

导航