42 接雨水
题目链接
思路
首先可以看到,对于一个位置水的高度,取决于右边第一个不小于它的高度的柱子。通过单调栈可以轻松找出右边第一个大于等于自身的柱子。
如何计算水的容量?按高度计算,对于一个池的而言,每一处位置的水的高度 = min(左,右)- 柱子高度,最后相加就是该处池子的水容量。
问题:按列计算难以判断池子的左边界。有多种情况:左边比右边小;当前左边比右边小,但更左边有更大的;以及递减之类。按列会比较难受。因此改用按行计算。
将计算逻辑变动一下即可:当遍历元素大于栈顶元素(递减栈)时,形成凹槽,分别计算凹槽的长和宽,相乘。
文章详解
cpp
class Solution {
public:
int trap(vector<int>& height) {
int sum = 0;
if(height.size() <= 2){
return sum;
}
stack<int> st;
st.push(0);
for(int i = 1; i < height.size(); i++)
{
if(height[i] < height[st.top()]){
st.push(i);
}else if(height[i] == height[st.top()]){
st.pop();
st.push(i); //保留右边的
}else {
while(!st.empty() && height[st.top()] < height[i]){ //
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; //注意减一
sum += h * w;
}
}
st.push(i);
}
}
return sum;
}
};
84 柱状图最大矩形
题目链接
思路
与接雨水相反,这里要变成右边第一个小于它的,递增栈
文章详解
cpp
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
stack<int> st;
heights.insert(heights.begin(), 0); // 数组头部加入元素0
heights.push_back(0); // 数组尾部加入元素0
st.push(0);
int result = 0;
for (int i = 1; i < heights.size(); i++) {
while (heights[i] < heights[st.top()]) {
int mid = st.top();
st.pop();
int w = i - st.top() - 1;
int h = heights[mid];
result = max(result, w * h);
}
st.push(i);
}
return result;
}
};