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.

leetcode  Largest Rectangle in Histogram

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

leetcode  Largest Rectangle in Histogram

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

For example,
Given heights = [2,1,5,6,2,3],
return 10.

网上找到一个解法,是用栈来解决。解法思想如下:

定义两个栈,一个存储矩形的高度,一个存储index,用来计算宽度。

我们首先分析一种情况,如果对于一个递增的数列,例如{1,2,3,4,5},那么,他的最大值情况很好分析。

即,1*5,2*4,3*3,4*2,5*1这5种情况,那么最大值显然为9。所以,我们首先考虑,如果遇到递增的子数列,

我们只需按照上面的方法来处理该递增子数列,即可得到对于这个子数列的最优解。

因此,如果当前处理的index处于一个递增子数列中,那么只是简单的将index和a[index]分别入栈即可。

当走到该递增子数列的终点时,即a[i]<a[i-1]时,结算之前的递增子数列。

此时,重点来了,在结算该递增子数列时,并不要结算ALL,例如,对于1,2,3,4,5,3这一数列来说,当index指向a[5]时,

开始弹出栈,结算。然而只结算到a[i]>a[5]的那部分,即结算4,5这两个点。为什么?

因为对于a[i]>a[5]的数来说,a[5]是一个凹陷,采用他们的值作为高度的矩形不会超过a[5]这个点,而这一结论对a[i]<=a[5]

的部分并不成立,也就是说,对于例子中的a[1],以它的值作为高度的矩形有可能越过a[5]这个点。因此在将这个点记录下来。并且记录它

往左边的尽头。最后再进行结算。给出代码:

public class Solution {

	/**
	 * @param args
	 */

	// O(n) using two stacks  
	public int largestRectangleArea(int[] height) {  
	  // Start typing your Java solution below  
	  // DO NOT write main() function  
	  int area = 0;  
	  java.util.Stack<Integer> heightStack = new java.util.Stack<Integer>();  
	  java.util.Stack<Integer> indexStack = new java.util.Stack<Integer>();  
	  for (int i = 0; i < height.length; i++) {  
		  System.out.println(heightStack);System.out.println(indexStack); 
	    if (heightStack.empty() || heightStack.peek() <= height[i]) {  
	      heightStack.push(height[i]);  
	      indexStack.push(i);  
	    } else if (heightStack.peek() > height[i]) {  
	      int j = 0;  
	      while (!heightStack.empty() && heightStack.peek() > height[i]) {  
	        j = indexStack.pop();  
	        int tmp=heightStack.pop();
	        int currArea = (i - j) * tmp;  
	        System.out.println("i="+i+",j="+j+"tmp="+tmp);
	        if (currArea > area) {
	        	
	          area = currArea;  
	        }  
	      }  
	      heightStack.push(height[i]);  
	      indexStack.push(j);  
	    }  
	  }  
	  System.out.println(heightStack);
	  System.out.println(indexStack);
	  while (!heightStack.empty()) {  
	    int currArea = (height.length - indexStack.pop()) * heightStack.pop();  
	    if (currArea > area) {  
	      area = currArea;  
	    }  
	  }  
	  return area;  
	} 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int [] nums={1,2,3,4,5,6,3,4,5,2};
		System.out.println(new Solution().largestRectangleArea(nums));
	}

}