单调栈算法学习

单调栈中存放的数据一般是有序的,所以单调栈也分为单调递增栈单调递减栈

单调递增栈就是从栈底到栈顶数据是从大到小单调递减栈就是从栈底到栈顶数据是从小到大。  

cpp栈的用法 :

创建栈 stack<类型> 变量名

  1. push(): 向栈内压入一个成员;
  2. pop(): 从栈顶弹出一个成员;
  3. empty(): 如果栈为空返回true,否则返回false;
  4. top(): 返回栈顶,但不删除成员;
  5. size(): 返回栈内元素的大小;

 力扣84. 柱状图中最大的矩形 - 力扣(LeetCode)

 此题构造单调递增栈

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        heights.push_back(-1);//构造单调递增的栈,往数组最后插入一个非常小的数
        stack<int>st;
        int ans=0,k=0;
        for(int i=0;i<heights.size();i++)
        {
            if(st.empty()||heights[i]>=heights[st.top()]){
                st.push(i);//当数组元素大于等于栈顶元素时将数组下标插入栈中
            }
            else{
                while(!st.empty()&&heights[i]<heights[st.top()])
                {   
                    k=st.top();//将栈顶元素的值存储
                    ans=max(ans,heights[st.top()]*(i-st.top()));//计算图形面积
                    st.pop();//将栈顶元素弹出
                    
                }
                st.push(k);//将之前的栈顶元素入栈
                heights[k] = heights[i];//把i对应的值赋给栈顶元素
            }
        }
        return ans;
    }
};

 关于这一部分为什么不能写st .push(i)。

st.push(k);
heights[k] = heights[i];

/*
为什么不能写为
st.push(i);
*/

例如heights=[2,1,2]的情况下,刚开始时2进栈(栈内元素用橙色标明,未进栈的用蓝色)

i和top进行比较

 由于i指针指向的值小于top指向的值,根据代码计算ans为2*1=2,同时弹出栈顶元素

假设我们此时的代码是st .push(i),那么就会变成这样,

此时i指针再次后移指向-1,栈中所有元素出栈,ans计算答案得到最大值为1*2为2

但实际上这题的最大值为3 这样的情况才是最大值

当我们用这段代码时 st.push(k);heights[k] = heights[i];将最开始的下标存入栈中,然后把值改为i的值。相当于把比heights[i]大的值用下标的形式存起来了(比heights[i]大的值事实上已经移出栈外,但是通过下标的差值来计算面积时仍然相当于参与了进去)

当i指向-1的位置时,计算ans得到ans=1*3=3,返回ans,就是我们要找的正确答案。 

力扣739. 每日温度 - 力扣(LeetCode)

此题为单调递减栈 

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int n=temperatures.size();
        vector<int>res(n,0);//创建一个n个0的数组
        stack<int>st;//创建一个栈
        for(int i=0;i<n;i++){
            while(!st.empty()&&temperatures[i]>temperatures[st.top()]){
                //只要温度大于栈顶温度且栈内非空
                auto t=st.top();//先将栈顶元素用变量存起来
                st.pop();//弹出栈顶元素
                res[t]=i-t;//计算第t天到第i天隔的时间
            }
            st.push(i);//将i入栈
        }
        return res;//返回答案数组
    }
};

当进行到75,71,69入栈后

此时72入栈,72大于69,数组res[4]值修改为5-4=1,69出栈。仍满足while循环继续比较,72大于71,数组res[3]的值修改为5-3=2,71出栈。72小于75,不满足while循环条件,72入栈。运行完毕后返回res数组即为正确答案。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值