题目:给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例:
输入: [2,1,5,6,2,3]
输出: 10
解决思路:
1、求的是面积 所以关注面积=高度宽度
2、最大面积 ==》肯定会用到res=Math.max(res,heightwidth)
3、总结1和2 得出主要是高度height 和宽度width怎么计算。
3.1 我们想着使用每个柱形作为高度 计算它作为高度时的最大宽度,即它所对应的最大矩形。
3.2 如何找每个柱形作为高度时的宽度呢:
3.2.1 从该柱形往左边延伸, 找到最后一个大于等于该柱形高度的最左边的一个柱。left
3.2.2 从该柱形往右边延伸, 找到最右边的最后一个大于等于该柱形高度的一个柱 right
3.2.3 width= right-left+1;
3.3 总结上述大致思路
3.3.1 首先for遍历数组中每一个柱形
3.3.2 针对每一个柱子 分别向左边延伸 向右边延伸
这个方法是一个暴利方法 时间复杂度O(n^2)
空间复杂度 O(1)
class Solution {
public int largestRectangleArea(int[] heights) {
int len = heights.length;
if(len<=0) return 0;
if(len==1) return heights[0];
int res=0;
for(int i=0;i<len;i++){
int curHeight=heights[i];
int left=i;
while(left>0&&heights[left-1]>=curHeight){
left--;
}
int right=i;
while(right<len-1&&heights[right+1]>=curHeight){
right++;
}
int curWidth=right-left+1;
res = Math.max(res,curHeight*curWidth);
}
return res;
}
}
4、为了优化上述的暴力方法
进一步分析,是否可以边遍历的时候,存储一些信息,
4.1因为存储下标的话 可以通过下标随机访问到数组中的高度值
所以我们一般存储索引
(在下面我想直接引入哨兵的做法, 直接免去我们对栈是否为空的判断)
4.2 以上述的[2,1,5,6,2,3]为例,
首先使用System.arraycopy(height,0,newHeight,1,len),将旧的数组拷贝。newHeight的数组长度为len+2.对于原数组最左边和最右边都各自增加了一个哨兵,因为这两个哨兵的柱高度可以看完0,所以栈中不会出现遍历整个数组之后出现栈不空的情况,同时不会出现栈空的情况,因为栈中第一个值为0, 数组中的值都大于0,所以0不会出栈,栈不会为空。
4.2.1 newHeight=[0,2,1,5,6,2,3,0] 注意 这个是一个单调非递减栈。
直接看
栈以及哨兵的详解
class Solution {
public int largestRectangleArea(int[] heights) {
int len=heights.length;
if(len<=0) return 0;
if(len==1) return heights[0];
int[] newHeight = new int[len+2];
Deque<Integer> stack = new ArrayDeque<Integer>();
newHeight[0]=0;
System.arraycopy(heights,0,newHeight,1,len);
heights = newHeight;
len+=2;
newHeight[len-1]=0;
stack.addLast(0);
int res=0;
for(int i=1;i<len;i++){
while(heights[i]<heights[stack.peekLast()]){
int curHeight=heights[stack.pollLast()];
//while(heights[stack.peekLast()]==curHeight){
//stack.pollLast();
//}
int curWidth=i-stack.peekLast()-1;
res=Math.max(res, curWidth*curHeight);
}
stack.addLast(i);
}
return res;
}
}