class Solution {
public:
int trap(vector<int>& height) {
if (height.size() < 3) return 0;
stack<int> st;
int result=0;
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()]){
while (st.size() > 1 && height[i] > height[st.top()]){
int lower = st.top();
st.pop();
result += (min(height[st.top()], height[i]) - height[lower]) * (i - st.top() - 1);
}
if (height[st.top()] < height[i]){
st.pop();
}
st.push(i);
}
}
return result;
}
};
接雨水的解题关键在于要找到坑的左右边界,左右边界一定比坑底高,所以要点就在于寻找一个位置的左右的更高点,所以构造的单调栈就应该是单调下降的,在遇到比栈顶更大的数据时就弹出栈顶数据,新的栈顶因为堆栈单调下降的特性,一定比刚弹出的要大,以两侧的更小值减去坑底大小再乘上距离就能得到填上这个小坑所需要的水,直到栈顶元素大于新的元素,就代表这个局部的坑已经填上了,值得说明的是,遇到相等大小的元素也需要直接入栈,以免在计算中的距离比实际的大。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
stack<int> st;
heights.push_back(0);
heights.insert(heights.begin(), 0);
int mx=0;
st.push(0);
for (int i = 1; i < heights.size(); i++){
if (heights[i] > heights[st.top()]){
st.push(i);
}else{
while (st.size() > 1 && heights[i] < heights[st.top()]){
int mid = st.top();
st.pop();
mx = max(mx, heights[mid] * (i - st.top() - 1));
}
st.push(i);
}
}
return mx;
}
};
这题与接雨水属于是一体双生,接雨水需要找到一个元素左右第一个更大的点,求矩形需要找到一个元素左右第一个更小的点,所以单调栈需要是单调递增的,这题中遇到与栈顶相同的元素就只需要略过就行,此外,在左右两侧加入0是为了让所有非零元素左右都有更小值。