42. 接雨水
思路:为了知道每个柱体上面水的深度,我们需要求该柱体左右两侧第一个比他大的元素,也就是比他高的柱子,当前水的体积就是 两个柱子之间的宽度 x (矮的那个柱子的高度 - 当前柱子的高度)。所以可以运用单调栈,当遇到比栈顶元素小的元素则入栈,遇到大的则出栈,把该栈头元素当作水底高度,此时新的栈头元素为水底两边高的柱子的一个,此时再求这两个柱子间的距离就可以计算了。在遍历的过程中不断累加雨水体积,在遍历结束后得到的result就是所能接的雨水体积。
代码:
class Solution {
public:
int trap(vector<int>& height) {
//从栈头到栈尾单调递增
//如果当前元素大于栈顶元素 则弹出一个栈顶元素 记录为mid
//记录为则当前雨水深度为 宽 * (min(当前元素,栈顶元素)-mid)
vector<int> res;
stack<int> stk;
stk.push(0);
int ans=0;
for(int i=1;i<height.size();i++){
while(!stk.empty()&&height[i]>height[stk.top()]){
int mid=stk.top();
stk.pop();
if(!stk.empty()){
int h = min(height[i],height[stk.top()])-height[mid];
int k= i-stk.top()-1;
ans += h*k;
}
}
stk.push(i);
}
return ans;
}
};
84.柱状图中最大的矩形
思路:和接雨水相比 接雨水求的是柱体两边的第一个更高的柱子 这道题求的是两边第一个更矮的柱子。此题便是单调递减栈,遍历到每一个元素都要 找到当前元素两边比它小的元素。由于必须柱体碰到比他矮的柱子才能计算体积,所以我们要在数组的两边各加一个0,使两边的柱子最低高度为0,保证可以计算。当 当前元素大于栈头元素时,该元素入栈,否则小于时栈头元素就作为计算用的最高点,然后栈头元素出栈,新的栈头元素作为边界用于计算宽度。这样体积=高度x两个边界之间的宽度。然后不断更新最大体积,最后剩下的最大体积就是所能勾勒的矩形最大面积。
代码:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
//单调递减栈 从栈头到栈尾递减
//遍历到每一个元素都要 找到当前元素两边比它小的元素
//首先要给数组前后都加0
heights.insert(heights.begin(),0);//头加0
heights.push_back(0);//尾加0
stack<int> stk;
int res=0;
stk.push(0);
for(int i=1;i<heights.size();i++){
while(!stk.empty()&&heights[i]<heights[stk.top()]){
//如果当前元素小于栈头元素 那么栈头元素为高度 当前下标为左边界
int mid=stk.top();
stk.pop();//弹出后的新的栈顶元素为新的右边界 因为它小于设定的mid
int high=heights[mid];
int wide=i-stk.top()-1;//矩形宽度
res=max(res,high*wide);
}
stk.push(i);
}
return res;
}
};