Largest Rectangle in Histogram

127 阅读1分钟

题目

Given an array of integers heights representing the histogram's bar height where the width of each bar is 1, return the area of the largest rectangle in the histogram.

image.png

Input: heights = [2,1,5,6,2,3]
Output: 10
Explanation: The above is a histogram where width of each bar is 1.
The largest rectangle is shown in the red area, which has an area = 10 units.

Constraints:

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

解答

  1. intuitive thoughts 对于最佳情况,即最大长方形而言,它一定有一个最矮的bar i,作为它的高度,左右两个边界的距离作为它的长度。左边界一定比左边界左一格的bar高,右边界一定比右边界右一格的bar高(若不满足,则这个就不是最大的长方形了,它还能向外扩展)。

那么我可以对任意一个bar i,假设以它作为最矮的那个,找到它的左右边界,得到一个area,遍历整个height数组,比较这些area获取最大值 ==> O(N2)

  1. 通过单调栈(monotonic stack)进行优化 达到O(N) 单调栈:即栈内元素大小从栈底到栈顶是由小到大,若遇到一个新的元素小于栈顶元素,则pop()栈顶元素,直到栈顶元素小于这个新的元素或栈为空,再add这个元素。

具体实现: 我们考虑相邻两个bar i和bar i+1,若heights[i] > heights[i+1],那么以i作为最矮的那个(即rectangle的高度)的长方形的右边界就是他本身,而左边界是向左看第一个比它矮的右边一格(也就是单调栈内它的前一个元素idx+1)。

若heights[i] <= heights[i+1],那么以i作为最矮的那个的长方形的右边界是向右看第一个递减bar的左边一格,左边界和上述一致。

因此,根据heights数组维护一个单调栈,当遇到heights[i+1] < heights[i]时,pop()出栈内大于它的元素,而每次pop()都能找到以i作为最矮的那个的长方形的面积,囊括了所有的情况。

class Solution {
    public int largestRectangleArea(int[] heights) {
        int max = 0;
        int n = heights.length;
        Stack<Integer> monotonicStack = new Stack<>();
        
        for (int i = 0; i <= n; i++) {
            int curHeight = i == n ? 0 :heights[i];
            while (!monotonicStack.isEmpty() && curHeight < heights[monotonicStack.peek()]) {
                //遇到了一个下降
                int peekIdx = monotonicStack.pop();
                int preMaxHeight = heights[peekIdx];
                int width = monotonicStack.isEmpty()? i : i - monotonicStack.peek() -1;
                max = Math.max(max, preMaxHeight * width);
            }
            monotonicStack.add(i);
        }  
        return max;
    }
}