题目描述
有一个直方图,用一个整数数组表示,其中每列的宽度为1,求所给直方图包含的最大矩形面积。比如,对于直方图[2,7,9,4],它所包含的最大矩形的面积为14(即[7,9]包涵的7x2的矩形)。
给定一个直方图A及它的总宽度n,请返回最大矩形面积。保证直方图宽度小于等于500。保证结果在int范围内。
测试样例:
[2,7,9,4,1],5
返回:14
这个题有点意思。首先一点思想就是,如果从图上做切割。那么肯定是要左右两边都照顾到。可是按照道理来讲,如果往左边遍历检查的话不是一个好方法,因为,实际上我们从左边过来的,一定有某种记忆方法不让他往左边递归。这样可以降低程序的复杂度。
我们用的就是一个栈。从左边递归过来。要保持栈是逐渐递增的。
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.。
这样做的好处就是。当我们发现要进来的元素比较小的时候,那么我们要出栈。所有大于这个元素都要出,因为这代表了在他们点进行分割。且不用考虑左边,因为左边
1如果左边那么不用考虑。stack.pollLast()*count
2如果左边相等,也不用考虑,因为左边元素也要出。
最后在元素遍历过后,栈里面会剩余一些元素。我们可以添加一个0高度的。或者直接编码处理。
import java.util.*;
public class MaxInnerRec {
public static void main(String args[])
{
MaxInnerRec obj=new MaxInnerRec();
System.out.println( obj.countArea(new int[]{2,7,9,4,1},5));
}
public int countArea(int[] A, int n) {
LinkedList<Integer> stack=new LinkedList<Integer>();
int i=0;
int result=0;
while(i<A.length)
{
if(stack.size()==0||stack.peekLast()<A[i])
{
stack.add(A[i]);
}
else
{
int count=0;
while(stack.size()!=0&&stack.peekLast()>A[i])
{
count++;
result=Math.max(result, stack.pollLast()*count);
}
while(count-->=0)
{
stack.add(A[i]);
}
}
i++;
}
int count=0;
while(stack.size()!=0)
{
count++;
result=Math.max(result, stack.pollLast()*count);
}
return result;
}
}