leetcode 84. 柱状图中最大的矩形 hard (重要)
题目描述:
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
解题思路:
遍历每根柱子,求以这根柱子为高,最大的矩形面积,那矩形的宽也就是求它左右两边各自最近比它小的元素下标-1
用单调栈来解题,对于每个元素求它左右两边各自最近比它小的元素。
代码:
//正确解法
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n=heights.size();
vector<int> left(n),right(n);
// 第一个比它小的,所以维持严格 从小到大的栈
// 存的是下标
stack<int> stk;
// 从左到右
for(int i=0;i<n;++i){
while(stk.size() && heights[stk.top()]>=heights[i]) //破坏了单调性
stk.pop();
if(stk.empty())
left[i]=-1;
else
left[i]=stk.top();
stk.push(i);
}
while(stk.size())
stk.pop();
// 从右到左
for(int i=n-1;i>=0;--i){
while(stk.size() && heights[stk.top()]>=heights[i])
stk.pop();
if(stk.empty())
right[i]=n;
else
right[i]=stk.top();
stk.push(i);
}
int res=0;
for(int i=0;i<n;++i)
res=max(res,(right[i]-left[i]-1)*heights[i]);
return res;
}
};
//也正确 但不nice
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
if(heights.empty())
return 0;
stack<int> inc; //求左右两边第一个小的,用递增栈
int res=0;
for(int i=0;i<heights.size();++i){
// 当等于的时候,也开始处理,为了代码好写
// 所以变成了右边是第一个小于等于它的下标
while(inc.size() && heights[i]<=heights[inc.top()]){
int index=inc.top();
inc.pop();
int start= inc.empty()?-1:inc.top();
int cur_height=(i-start-1)*heights[index];
res= max(res,cur_height);
}
inc.push(i);
}
//数组遍历完了,但是栈里还有元素
// 这时候他们的右边 第一个小于它们的就是右边界(数组长度)
// 左边 第一个小于的就是栈里被它压的下一个元素(假如没有被压的,就是-1)
int end=heights.size();
while(inc.size()){
int index=inc.top();
inc.pop();
int start=inc.empty()?-1:inc.top();
int cur_height=(end-start-1)*heights[index];
res = max(res,cur_height);
}
return res;
}
};