1.接雨水
代码:
class Solution {
public:
int trap(vector<int>& height) {
int result = 0;
if(height.size() <= 2) return result;
stack<int> st;
st.push(0);
for(int i = 1; i < height.size(); i++){
while(!st.empty() && height[i] > height[st.top()]){
int mid = st.top();
st.pop();
if(!st.empty()){
int h = min(height[i], height[st.top()]) - height[mid];
int w = i - st.top() - 1;
result += h * w;
}
}
st.push(i);
}
return result;
}
};
note:
这道题和前面的单调栈问题的区别在于,它要找到自己两边第一个比自己大的元素,之前我们只是求右边第一个大的元素,不过其实左边第一个大的元素就是在栈里和自己紧挨着的元素。
再有就是思路上的难点了,这里的计算面积其实是按照行来计算的。我们找到当前元素左右两边第一个比自己大的元素,那么我们要算的雨水的面积的高就是——左右两边的第一个比自己高的柱子的最小值 - 自己的高;雨水面积的宽就是——这两个柱子的下标相减再减1(为什么减1就自己看图想想)
2.柱状图中最大的矩形
代码随想录 (programmercarl.com)
视频:单调栈,又一次经典来袭! LeetCode:84.柱状图中最大的矩形_哔哩哔哩_bilibili
代码:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int result = 0;
stack<int> st;
heights.insert(heights.begin(), 0);
heights.push_back(0);
st.push(0);
for(int i = 1; i < heights.size(); i++){
while(!st.empty() && heights[i] < heights[st.top()]){
int mid = st.top();
st.pop();
if(!st.empty()){
int w = i - st.top() - 1;
int h = heights[mid];
result = max(w * h, result);
}
}
st.push(i);
}
return result;
}
};
note:
和上一题的区别是:
前一题用单调递增栈,这题用单调递减栈。
前一题接雨水的两边自有矩形把雨水括在里面,但是此题是求柱状图里的矩形——我们要人为的在两端添加0来使得所有的矩形情况都被我们遍历到。
在首端添加0——为了防止最后一个矩形的计算找不到它左边比它第一个小的元素
在末尾添加0——为了防止所有的元素符合单调递减栈的顺序,导致没有触发计算矩形面积的逻辑。