LeetCode – Largest Rectangle in Histogram (Java)

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.

largest-rectangle-in-histogram1

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

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

For example, given height = [2,1,5,6,2,3], return 10.

Analysis

The key to solve this problem is to maintain a stack to store bars' indexes. The stack only keeps the increasing bars.

Java Solution

public int largestRectangleArea(int[] height) {
	if (height == null || height.length == 0) {
		return 0;
	}
 
	Stack<Integer> stack = new Stack<Integer>();
 
	int max = 0;
	int i = 0;
 
	while (i < height.length) {
		//push index to stack when the current height is larger than the previous one
		if (stack.isEmpty() || height[i] >= height[stack.peek()]) {
			stack.push(i);
			i++;
		} else {
		//calculate max value when the current height is less than the previous one
			int p = stack.pop();
			int h = height[p];
			int w = stack.isEmpty() ? i : i - stack.peek() - 1;
			max = Math.max(h * w, max);
		}
 
	}
 
	while (!stack.isEmpty()) {
		int p = stack.pop();
		int h = height[p];
		int w = stack.isEmpty() ? i : i - stack.peek() - 1;
		max = Math.max(h * w, max);
	}
 
	return max;
}
Category >> Algorithms >> Interview  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • Jon Bramley

    My solution:


    private static double solution(double[] hist) {
    Stack pStack = new Stack(), hStack = new Stack();
    double insertPos, cHeight, potMax, maxA = 0;

    for (int i = 0; (insertPos = i) cHeight)
    if ((potMax = (i - (insertPos = pStack.pop())) * hStack.pop()) >= maxA)
    maxA = potMax;

    if (hStack.isEmpty() || hStack.peek() != cHeight) {
    pStack.push(insertPos);
    hStack.push(cHeight);
    }
    }
    return maxA;
    }

  • AJ


    int maxArea(int[] a) {
    if (a == null || a.length == 0) {
    return 0;
    }
    int max = 0;
    for (int i = 0; i 0 && a[j] >= a[i]; j--) {
    width++;
    }

    for (int j = i + 1; j = a[i]; j++) {
    width++;
    }
    max = Math.max(max, a[i] * (width));
    }
    return max;
    }

  • Anusha

    Does this work for 2,4,5,6,7? Wouldn’t it throw IndexOutOfBoundsException when you do height[7] in the second while loop, after you do stack.pop()?

  • Shariq Aziz

    Can someone explain how this works? The analysis behind it? Thanks. I came up with and n^2 time and constant space solution using the left, right approach but can’t grasp this proposed solution

  • Elvira Gandelman

    yup, you can easily prove it’s not working by using something smallish, something bigger, something smallest… 🙂 like 2, 3, 1 is the simplest case.

  • Snail914

    This is a good solution, but still takes o(n^2) in the worse case: {1, 2, 4, 5, 6, 8, 10…}

  • Thompson Hu

    int w = stack.isEmpty() ? i : i – stack.peek() – 1;
    Why “-1”? Could someone tell me? Pls use [1 ,4 ,2] to walk through.

  • jason zhang

    some observation:
    maxLeft[i]: trace back from i to left, the first index with a value less than bar[i];
    maxRight[i]: trace forward from i to right, the first index with a value than bar[i];
    The max area around i: is bar[i]*( maxRight[i]-maxLeft[i]-1)

  • Jason Zhu

    Test cases:

    System.out.println(solution(new int[]{2,1,5,6,2,3}));
    System.out.println(solution(new int[]{2,1,0,6,2,3}));
    System.out.println(solution(new int[]{2,1,2,6,1,7,1,0,6,2,3}));

  • Jason Zhu

    An O(N) solution via iteration using Dynamic Programming:

    public static int solution(int[] bar) {

    //parameter check

    assert (bar != null && bar.length > 0);

    //initialization

    int[] maxLeft = new int[bar.length];

    int[] maxRight = new int[bar.length];

    maxLeft[0] = -1;

    maxRight[bar.length-1] = bar.length;

    int maxArea = -1;

    //calculate maxLeft

    for(int i = 1; i = 0) {

    if (bar[i] > bar[leftCur]) {

    break;

    }

    else {

    leftCur = maxLeft[leftCur];

    }

    }

    maxLeft[i] = leftCur;

    }

    //calculate maxRight

    for(int i = bar.length-2; i >= 0; –i) {

    int rightCur = i+1;

    while(rightCur bar[rightCur]) {

    break;

    }

    else {

    rightCur = maxRight[rightCur];

    }

    }

    maxRight[i] = rightCur;

    }

    //find max

    for(int i = 0; i maxArea) maxArea = curSize;

    }

    return maxArea;

    }

  • aegis

    How is this O(n)?

  • Satish

    You are making it too complicated. Here is simple solution for this problem:

    public static int largestRectArea(int[] height) {
    int max = 0;
    if (height.length == 0 || height == null) {
    return 0;
    }
    int i = 0;
    while (i = 0) {
    if (height[j] < h) {
    h = height[j];
    max = Math.max(height[j] * (i – j + 1), max);
    } else {
    max = Math.max(h * (i – j + 1), max);
    }
    j–;
    }
    i++;
    }
    return max;
    }