一、LeetCode 84. 柱状图中最大的矩形
题目链接/文章讲解/代码讲解:https://programmercarl.com/0084.%E6%9F%B1%E7%8A%B6%E5%9B%BE%E4%B8%AD%E6%9C%80%E5%A4%A7%E7%9A%84%E7%9F%A9%E5%BD%A2.html
状态:已解决
1.思路
这道题跟上道接雨水的题基本上是反着来的,在题解42. 接雨水 (opens new window)中我讲解了接雨水的单调栈从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。那么因为本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的顺序。
只有栈里从大到小的顺序,才能保证栈顶元素找到左右两边第一个小于栈顶元素的柱子。所以本题单调栈的顺序正好与接雨水反过来。此时大家应该可以发现其实就是栈顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度
其余与接雨水问题基本一致了。
不过,注意:
①如果数组本身就是升序的,例如[2,4,6,8],那么入栈之后 都是单调递减,一直都没有出现当前遍历元素小于栈顶元素的情况,所以最后输出的就是0了。因此我们在heights末尾加上一个0,让所有元素都满足这个情况。
②如果数组本身是降序的,例如 [8,6,4,2],在 8 入栈后,6 开始与8 进行比较,此时我们得到 mid(8),rigt(6),但是得不到 left。因为 将 8 弹出之后,栈里没有元素了,那么为了避免空栈取值,直接跳过了计算结果的逻辑。之后又将6 加入栈(此时8已经弹出了),然后 就是 4 与 栈口元素 8 进行比较,周而复始,那么计算的最后结果resutl就是0。故我们要在heights数组前面加一个元素,以防止取不到最左边的情况。
2.代码实现
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
heights.insert(heights.begin(), 0);
heights.push_back(0);
int s=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 top = st.top();
st.pop();
if(!st.empty()){
int left = st.top();
int w = i-left-1;
int h = heights[top];
s = max(s,h*w);
}
}
st.push(i);
}
}
return s;
}
};