LeetCode: 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.
本来的想法就是最naive的想法。对应每一个bar,在它的左右两侧延伸,直到遇到一个比这个值小的bar,计算面积。
可以通过,就是时间比较长。
后来在网上看到一种O(n)的算法。。我发现很多我做出来的题都不是最优的算法,都是一些naive的算法。
Actually, we can decrease the complexity by using stack to keep track of the height and start indexes. Compare the current height with previous one.
Case 1: current > previous (top of height stack)
Push current height and index as candidate rectangle start position.
Case 2: current = previous
Ignore.
Case 3: current < previous
Need keep popping out previous heights, and compute the candidate rectangle with height and width (current index - previous index). Push the height and index to stacks.
每一次弹出来一个值的时候,用这个值乘上它与当前值横坐标的差,就可以计算出以被弹出的值为当前值,向两侧延伸,所得到的面积。
这是因为在入栈的时候,之前的肯定是要比他小的。现在又遇到一个比他小的,所以这个范围一定是他的最大范围。
最后所有元素处理之后,还有没弹出栈的,说明这个值在他后面一直没有遇到比他小的。所以它可以一直延伸到数组的末尾。
1 public int largestRectangleArea2(int[] height) { 2 if (height == null || height.length == 0) return 0; 3 4 int maxArea = 0; 5 Stack<Integer> stackHeight = new Stack<Integer>(); 6 Stack<Integer> stackIndex = new Stack<Integer>(); 7 8 for (int i = 0; i < height.length; i++) { 9 //case 1 10 if (stackHeight.isEmpty() || height[i] > stackHeight.peek()) { 11 stackHeight.push(height[i]); 12 stackIndex.push(i); 13 } else if (height[i] < stackHeight.peek()) { 14 // case 3 15 int lastIndex = 0; 16 while (stackHeight.isEmpty() == false && height[i] < stackHeight.peek()) { 17 lastIndex = stackIndex.pop(); 18 int tempArea = stackHeight.pop() * (i - lastIndex); 19 if (maxArea < tempArea) { 20 maxArea = tempArea; 21 } 22 } 23 stackHeight.push(height[i]); 24 stackIndex.push(lastIndex); 25 } 26 } 27 28 while(stackHeight.isEmpty() == false) { 29 int tempArea = stackHeight.pop() * (height.length - stackIndex.pop()); 30 if (tempArea > maxArea) { 31 maxArea = tempArea; 32 } 33 } 34 return maxArea; 35 }