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.

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 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));
	}

}

  

 

posted @ 2016-05-18 15:32  ElNinoT  阅读(165)  评论(0编辑  收藏  举报