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.

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

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.

**Thoughts:**

The point of this algorithm is to maintain a stack where higher element is always greater or equal to the lower element. Why do we need to maintain that kind of stack? Because if we have a non-decreasing list, we can easily calculate the maximum area in one scan. We just need to compare: height[i] * (n – i) for every i. So how do we maintain this stack? If we keep seeing larger element, we just need to push them onto the stack. If we see a smaller (compared to the top element on the stack) element, we need to do two things:

- Pop the stack until we can maintain the non-decreasing order. Pushing the smaller element for m times, where m = number of poped elements.
- Keep track of the maximum area that cause by those pop.

For example, we have height = {1,3,5,7,4}.

We push onto the stack for {1,3,5,7} then we see 4. 4 is less than 7, so we need to pop. We stop popping until we see 3. However many times we pop, we push 4 onto the stack. Therefore the resulted stack would be {1,3,4,4,4}. Because of popping 7, we need to remember that the maximum area that contains 7 is 7. The largest area that contains 5, the other element which get popped, is 10. So we take that down. We then finish processing all the elements in the original array and end up with a non-decreasing stack {1,3,4,4,4}. We can compute the largest area of this stack, which is 4*3 = 12. Since 12 is larger than the previous largest, 10, we output 12.

**Code (Java):**

public class Solution { public int largestRectangleArea(int[] height) { Stack<Integer> stack = new Stack<Integer>(); int max = 0; int i = 0; while(i < height.length) { if(stack.isEmpty() || height[i] >= stack.peek()) { stack.push(height[i]); i++; } else { int count = 0; while(!stack.isEmpty() && stack.peek() > height[i]) { count++; int top = stack.pop(); max = Math.max(max, top * count); } for(int j = 0; j < count + 1; ++j) { stack.push(height[i]); } i++; } } int count = 0; while(!stack.isEmpty()) { count++; max = Math.max(max, stack.pop() * count); } return max; } }

Code (C++):class Solution { public: int largestRectangleArea(vector<int> &height) { stack<int> stack_; int maxArea = 0; int i = 0; while(i < height.size()) { if(stack_.empty() || height[i] >= stack_.top()) { stack_.push(height[i]); i++; } else { int count = 0; while(!stack_.empty() && stack_.top() > height[i]) { count++; int top = stack_.top(); stack_.pop(); maxArea = max(maxArea, top * count); } for(int j = 0; j < count + 1; ++j) { stack_.push(height[i]); } i++; } } int count = 0; while(!stack_.empty()) { count++; maxArea = max(maxArea, stack_.top() * count); stack_.pop(); } return maxArea; } };Advertisements

Daniel Fukuciro

Oct 14, 2012@ 15:47:27This solution in worst case is O(n²) isn’t it? Suppose this input: {5, 4, 3, 2, 1}. You take 5 and put in stack because it is empty. When you take 4 you’ll have to pop until stack is empty or top is <= 4 than put 4 x times, where x is the number of elements that you removed from you stack.

So, in this input for 5 you will just push it, for 4 you will pop until empty and put 2 times. For 3 you will pop until empty and put 3 times. T(n) = 1 + 2 + 3 + … + n = n(n + 1) / 2 = O(n²).

Guojing Yuan

Jan 25, 2014@ 17:30:33田兄google竟然能搜到你的答案。。。点个赞！