直方图上的最大矩形。这道题很有意思。研究了半天才研究出来是个什么意思。
首先看题目:
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));
}
}