代码随想录算法训练营第49天| 单调栈 42. 接雨水、84.柱状图中最大的矩形

42. 接雨水

题目链接: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.柱状图中最大的矩形

题目链接: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;
    }
};

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值