84.柱状图中最大的矩形
1.题目:
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 1:
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
https://leetcode.cn/problems/largest-rectangle-in-histogram
2.思路:
单调栈:
栈内从栈头到栈尾顺序 从大到小(向左边或者右边寻找比此元素小的 栈的顺序从从大到小)
给数组前后各添加两个元素0原因:
如果数组本身就是升序的,例如[2,4,6,8],那么入栈之后 都是单调递减,一直都没有走 情况三 计算结果的哪一步,所以最后输出的就是0了。 如图:
那么结尾加一个0,就会让栈里的所有元素,走到情况三的逻辑。
开头为什么要加元素0?
如果数组本身是降序的,例如 [8,6,4,2],在 8 入栈后,6 开始与8 进行比较,此时我们得到 mid(8),rigt(6),但是得不到 left。
(mid、left,right 都是对应版本一里的逻辑)
因为 将 8 弹出之后,栈里没有元素了,那么为了避免空栈取值,直接跳过了计算结果的逻辑。
之后又将6 加入栈(此时8已经弹出了),然后 就是 4 与 栈口元素 8 进行比较,周而复始,那么计算的最后结果resutl就是0。 如图所示:
所以我们需要在 height数组前后各加一个元素0。
3.代码:
public int largestRectangleArea(int[] heights) {
//单调栈
Stack<Integer> stack=new Stack<>();
int area=0;
int[] newHeights=new int[heights.length+2];
newHeights[0]=0;
newHeights[newHeights.length-1]=0;
for(int i=0;i<heights.length;i++){
newHeights[i+1]=heights[i];
}
stack.push(0);
for(int i=1;i<newHeights.length;i++){
if(newHeights[i]>newHeights[stack.peek()]){
stack.push(i);
}else if(newHeights[i]==newHeights[stack.peek()]){
stack.pop();
stack.push(i);
}else{
while(newHeights[i]<newHeights[stack.peek()]){
int mid=stack.peek();
stack.pop();
int left=stack.peek();
int right=i;
int sum=right-left-1;
int h=newHeights[mid];
area=Math.max(area,sum*h);
}
stack.push(i);
}
}
return area;
}