【LeetCode】84.柱状图中最大的矩形

题目链接

84. 柱状图中最大的矩形

题目描述

解题思路

暴力法

对于每一个高度height[i],我们可以向左向右遍历,然后算出该高度往左往右最多可以延申至何处,这样就能算出该高度对应的面积,枚举所有高度然后求出最大值。

时间复杂度:O(n)

空间复杂度:O(1)

超时!

单调栈

以上暴力写法 Java 可以通过,但我们不妨想一下这里的双重循环是否可以优化?

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

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

小trick:为长度数组首位加上两个0,便于计算,同时可以解决高度递增序列现象问题。

AC代码

暴力法

class Solution {
    public int largestRectangleArea(int[] heights) {
        int area = 0, n = heights.length;
        // 遍历每个柱子,以当前柱子的高度作为矩形的高 h,
        // 从当前柱子向左右遍历,找到矩形的宽度 w。
        for (int i = 0; i < n; i++) {
            int w = 1, h = heights[i], j = i;
            while (--j >= 0 && heights[j] >= h) {
                w++;
            }
            j = i;
            while (++j < n && heights[j] >= h) {
                w++;
            }
            area = Math.max(area, w * h);
        }

        return area;
    }
}

单调栈法

class Solution {
    public int largestRectangleArea(int[] heights) {
        int ans = 0;
        int cHeights[] = new int[heights.length+2];
        cHeights[0] = 0;
        cHeights[heights.length+1] = 0;
        for(int i = 1; i < heights.length+1; i++){
            cHeights[i] = heights[i-1];
        }
        Stack<Integer> st = new Stack<>();
        for(int i = 0; i < cHeights.length; i++){
            while(!st.isEmpty() && cHeights[i] < cHeights[st.peek()]){
                int height = cHeights[st.pop()];
                ans = Math.max(ans,height * (i - st.peek() - 1));
            }
            st.push(i);
        }
        return ans;
    }
}
posted @ 2020-12-26 20:13  控球强迫症  阅读(105)  评论(0编辑  收藏  举报