单调栈stack--c++

本文深入解析单调栈算法在解决接雨水、最大矩形等问题的应用。通过递增与递减栈处理,实现高效计算,适用于算法竞赛及面试准备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单调递减栈

在这里插入图片描述
遍历高度,如果此时栈为空,或者当前高度小于等于栈顶高度,则把当前高度的坐标压入栈,注意我们不直接把高度压入栈,而是把坐标压入栈,这样方便我们在后来算水平距离。当我们遇到比栈顶高度大的时候,就说明有可能会有坑存在,可以装雨水。此时我们栈里至少有一个高度,如果只有一个的话,那么不能形成坑,我们直接跳过,如果多余一个的话,那么此时把栈顶元素取出来当作坑,新的栈顶元素就是左边界,当前高度是右边界,只要取二者较小的,减去坑的高度,长度就是右边界坐标减去左边界坐标再减1,二者相乘就是盛水量啦,参见代码如下:

int trap(vector<int>& height) {
        stack<int> sta;
        int res=0;
        for(int i=0;i<height.size();++i)
        {
            if(sta.empty()||height[sta.top()]>=height[i]) sta.push(i);
            else
            {
                int j=sta.top();
                sta.pop();
                if(sta.empty())
                {
                    --i;
                    continue;  
                }
                res+=(min(height[i],height[sta.top()])-height[j])*(i-sta.top()-1);
                --i;
            }
        }
        return res;
    }

单调递增栈

在这里插入图片描述
我们可以看到,直方图矩形面积要最大的话,需要尽可能的使得连续的矩形多,并且最低一块的高度要高。有点像木桶原理一样,总是最低的那块板子决定桶的装水量。那么既然需要用单调栈来做,首先要考虑到底用递增栈,还是用递减栈来做。我们想啊,递增栈是维护递增的顺序,当遇到小于栈顶元素的数就开始处理,而递减栈正好相反,维护递减的顺序,当遇到大于栈顶元素的数开始处理。那么根据这道题的特点,我们需要按从高板子到低板子的顺序处理,先处理最高的板子,宽度为1,然后再处理旁边矮一些的板子,此时长度为2,因为之前的高板子可组成矮板子的矩形 ,因此我们需要一个递增栈,当遇到大的数字直接进栈,而当遇到小于栈顶元素的数字时,就要取出栈顶元素进行处理了,那取出的顺序就是从高板子到矮板子了,于是乎遇到的较小的数字只是一个触发,表示现在需要开始计算矩形面积了,为了使得最后一块板子也被处理,这里用了个小技巧,在高度数组最后面加上一个0,这样原先的最后一个板子也可以被处理了。由于栈顶元素是矩形的高度,那么关键就是求出来宽度,那么跟之前那道 接雨水 一样,单调栈中不能放高度,而是需要放坐标。由于我们先取出栈中最高的板子,那么就可以先算出长度为1的矩形面积了,然后再取下一个板子,此时根据矮板子的高度算长度为2的矩形面积,以此类推,知道数字大于栈顶元素为止,再次进栈,代码如下:

int largestRectangleArea(vector<int>& heights) {
        stack<int> sta;
        int res=0;
        heights.push_back(0);
        for(int i=0;i<heights.size();++i)
        {
            if(sta.empty()||heights[i]>=heights[sta.top()]) sta.push(i);
            else
            {
                int j= sta.top();
                sta.pop();
                res=max(res,heights[j]*(sta.empty()?i:i-1-sta.top()));
                --i;
            }
        }
        return res;
    }

扩展:最大矩形

在这里插入图片描述

 int maximalRectangle(vector<vector<char>>& matrix) {
        if(matrix.empty() || matrix[0].empty()) return 0;
        int m=matrix.size(),n=matrix[0].size(),res=0;
        vector<int> height(n,0);
        for(int i=0;i<m;++i)
        {
            for(int j=0;j<n;++j)
            {
                height[j]=matrix[i][j]=='0'?0:1+height[j];
            }
            res=max(res,large(height));
        }
        return res;
    }
    int large(vector<int>& height)
    {
        height.push_back(0);
        stack<int> sta;
        int res=0;
        for(int i=0;i<height.size();++i)
        {
            if(sta.empty()||height[i]>=height[sta.top()]) sta.push(i);
            else
            {
                int j=sta.top();
                sta.pop();
                res=max(res,height[j]*(sta.empty()?i:i-sta.top()-1));
                --i;
            }
        }
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值