- 题目描述
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
来源:LeetCode
- 示例
输入: [2,1,5,6,2,3]
输出: 10
- 思路分析
- 思路1:暴力双循环法。最后有几个例子无法通过,会超时。
- 思路2:单调栈法。选一个柱子,以这个柱子i的高度作为矩形的固定高度h。由于要面积尽可能大,所以我们希望矩形尽可能宽。当高度确定的时候,从柱子i能够左右延伸的最远距离是遇到的高度小于h的柱子,注意计算矩形并不包含这个边界柱。计算左右两边能延伸的最远距离就是用单调栈法。详解看官方的吧,有例子,说得很详细。
- JAVA实现
class Solution {
public int largestRectangleArea(int[] heights) {
/*
//双重循环法,超时
int minH = 0;
int maxArea = 0;
for(int i=0; i<heights.length; i++) {
if(heights[i] <= minH) continue;
for(int j=i; j<heights.length; j++) {
if(j == i) minH = heights[i];
else minH = Math.min(minH, heights[j]);
int area = minH*(j-i+1);
if(area>maxArea) maxArea = area;
}
}
return maxArea;
*/
Stack stack = new Stack();
int[] left = new int[heights.length]; //记录每个柱子向左能延伸的最远距离:即向左遇到的第一个高度小于这个柱子高度的柱子。
int[] right = new int[heights.length];
left[0] = -1;
stack.push(0);
for(int i=1; i<heights.length; i++) {
while(!stack.empty() && heights[i] <= heights[(int)stack.peek()]) stack.pop();
if(stack.empty()) left[i] = -1;
else left[i] = (int)stack.peek();
stack.push(i);
}
while(!stack.empty()) stack.pop(); //清空栈
right[heights.length-1] = heights.length;
stack.push(heights.length-1);
for(int j=heights.length-2; j>=0; j--) {
while(!stack.empty() && heights[j] <= heights[(int)stack.peek()]) stack.pop();
if(stack.empty()) right[j] = heights.length;
else right[j] = (int)stack.peek();
stack.push(j);
}
int maxA = 0;
for(int m=0; m<heights.length; m++) {
int area = (right[m] - left[m] - 1)*heights[m];
if(area>maxA) maxA = area;
}
return maxA;
}
}