LeetCode 84:柱状图中最大的矩形(单调栈)

题目

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

示例

输入: [2,1,5,6,2,3]
输出: 10
在这里插入图片描述

代码

暴力法

遍历每根柱子,以当前柱子 i 的高度作为矩形的高,那么矩形的宽度边界即为向左找到第一个高度小于当前柱体 i 的柱体,向右找到第一个高度小于当前柱体 i 的柱体。
对于每个柱子我们都如上计算一遍以当前柱子作为高的矩形面积,最终比较出最大的矩形面积即可。

class Solution {
    public int largestRectangleArea(int[] heights) {
        int res = 0;
        for(int i=0;i<heights.length;i++){
            int h = heights[i];
            int w = 1;
            int j = i-1;
            //先遍历左边
            while(j>=0&&heights[j]>=h){
                w++;
                j--;
            }
            j = i+1;
            //遍历右边
            while(j<heights.length&&heights[j]>=h){
                w++;
                j++;
            }
            res = Math.max(res,w*h);
        }
        return res;
    }
}

单调栈

我们每遍历到当前柱体 i 时:
上述写法中,我们需要再嵌套一层 while 循环来向左找到第一个比柱体 i 高度小的柱体,这个过程是 O(N) 的;
那么我们可以 O(1) 的获取柱体 i 左边第一个比它小的柱体吗?答案就是单调增栈,因为对于栈中的柱体来说,栈中下一个柱体就是左边第一个高度小于自身的柱体

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

class Solution {
    public int largestRectangleArea(int[] heights) {
        
        int[] array = new int[heights.length+2];
        System.arraycopy(heights,0,array,1,heights.length);
        int res = 0;
        //
        LinkedList<Integer> stack = new LinkedList<>();
        for(int i=0;i<array.length;i++){
            
            while(!stack.isEmpty()&&array[i]<array[stack.peek()]){
                /*如果当前柱体高度小于栈顶柱体的高度,
                说明当前栈顶柱体找到了右边的第一个小于自身的柱体,
                那么以它为高度的矩形面积可求
                */
                int index = stack.pop();
                res = Math.max(res,(i-stack.peek()-1)*array[index]);
            }
            /*栈顶柱体为左边第一个高度小于当前柱体的柱体,
            若当前的柱体高度大于等于栈顶柱体的高度,就直接将当前柱体入栈
            */
            stack.push(i);
        }
        return res;
    }
}

ps:这道题跟“接雨水”思想是一样的:单调栈

参考链接:详解单调栈,🤷‍♀️必须秒懂!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章