Largest Rectangle in Histogram

Largest Rectangle in Histogram

Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.

histogram

Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

histogram

The largest rectangle is shown in the shaded area, which has area = 10 unit.

Example

Given height = [2,1,5,6,2,3],
return 10.

Solution: max(the area of rectangle which height[i] is the shortest bar)

leftBound[i]: index of the first element less than height[i] starting from the left +1

rightBound[i]: index of the first element less than height[i] starting from the right -1

result = max(height[i]*(rightBound[i]-leftBound[i]))

注意:凡是求左边第一个比它小得数这类问题 用stack 存数组的index

策略是:

如果新来的数大于A[stack.peek()], 直接push i to stack, otherwise stack.pop()直到找到第一个比他小得数停下,push i to stack.

这样对一个array来说 只要走一遍就知道每一个数的左边第一个比它小的数是哪个。

O(n) time.

Solution 1. Straightforward Version

public int largestRectangleArea(int[] height) {
    if (height == null || height.length == 0) {
        return 0;
    }
    int[] leftBound = new int[height.length];
    int[] rightBound = new int[height.length];
    Stack<Integer> minStack = new Stack<>();
    for (int i = 0; i < height.length; i++) {
        while (!minStack.isEmpty() && height[i] <= height[minStack.peek()]) {
            minStack.pop();
        }
        if (minStack.isEmpty()) {
            leftBound[i] = 0;
        } else {
            leftBound[i] = minStack.peek() + 1;
        }
        minStack.push(i);
    }
    minStack = new Stack<>();
    for (int i = height.length - 1; i >= 0; i--) {
        while (!minStack.isEmpty() && height[i] <= height[minStack.peek()]) {
            minStack.pop();
        }
        if (minStack.isEmpty()) {
            rightBound[i] = height.length - 1;
        } else {
            rightBound[i] = minStack.peek() - 1;
        }
        minStack.push(i);
    }
    int maxArea = 0;
    for (int i = 0; i < height.length; i++) {
        int area = height[i] * (rightBound[i] - leftBound[i] + 1);
        maxArea = Math.max(maxArea, area);
    }
    return maxArea;
}

Solution 2. Fancy Version, One pass

public int largestRectangleArea(int[] height) {
    if (height == null || height.length == 0) {
        return 0;
    }
    Stack<Integer> minStack = new Stack<>();
    int maxArea = 0;
    for (int i = 0; i <= height.length; i++) {
        int curr = (i == height.length) ? -1 : height[i];
        while (!minStack.isEmpty() && curr <= height[minStack.peek()]) {
            int tmp = minStack.pop();
            int left = minStack.isEmpty() ? 0 : minStack.peek() + 1;
            int area = (i - left) * height[tmp];
            maxArea = Math.max(area, maxArea);
        }
        minStack.push(i);
    }
    return maxArea;
}
FacebookTwitterGoogle+Share

Leave a Reply

Your email address will not be published. Required fields are marked *