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