84.柱状图中最大的矩形
力扣题目链接(opens new window)
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
思路:
为什么这么说呢,42. 接雨水 (opens new window)是找每个柱子左右两边第一个大于该柱子高度的柱子,而本题是找每个柱子左右两边第一个小于该柱子的柱子。
这里就涉及到了单调栈很重要的性质,就是单调栈里的顺序,是从小到大还是从大到小。
在题解42. 接雨水 (opens new window)中我讲解了接雨水的单调栈从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。
那么因为本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的顺序!
我来举一个例子,如图:
只有栈里从大到小的顺序,才能保证栈顶元素找到左右两边第一个小于栈顶元素的柱子。
所以本题单调栈的顺序正好与接雨水反过来。
此时大家应该可以发现其实就是栈顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度
主要就是分析清楚如下三种情况:
- 情况一:当前遍历的元素heights[i]大于栈顶元素heights[st.top()]的情况
- 情况二:当前遍历的元素heights[i]等于栈顶元素heights[st.top()]的情况
- 情况三:当前遍历的元素heights[i]小于栈顶元素heights[st.top()]的情况
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int result=0;
heights.insert(heights.begin(),0);
heights.push_back(0);
stack<int>st;
st.push(0);
for(int i=1;i<heights.size();i++){
if(heights[i]>heights[st.top()]){
st.push(i);
}
else if(heights[i]==heights[st.top()]){
st.pop();
st.push(i);
}
else{
while(!st.empty()&& heights[i]<heights[st.top()]){
int mid =st.top();
st.pop();
if(!st.empty()){
int left =st.top();
// st.pop();
int right=i;
int w = right-left-1;
int h = heights[mid];
result=max(result, w*h);
}
}
st.push(i);
}
}
return result;
}
};
参考:代码随想录