【代码随想录】Day58~Day60单调栈

单调栈的作用

就是用一个栈来记录我们遍历过的元素

单调栈里存放元素下标i就可以了,如果要使用对应元素,直接T[i]就可以获取到

从栈头到栈尾-递增的话-栈里要加入一个元素i的时候,才知道栈顶元素在数组中右面第一个比栈顶元素大的元素是i

题目

LeetCode:739.每日温度

解法

将下标存放进单调栈中

当前遍历的元素和栈顶元素进行比较T[i]和T[st.pop()]

T[i]==T[st.pop()] 入栈

T[i]>T[st.pop()] 记录结果

T[i]<T[st.pop()] 入栈

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int> st;
        vector<int> reulst(temperatures.size(),0);
        st.push(0);//放入第一个元素
        for(int i=1;i<temperatures.size();i++){
            if(temperatures[i]<temperatures[st.top()]) st.push(i);
            else if(temperatures[i]==temperatures[st.top()]) st.push(i);
            else{
                while(!st.empty()&&temperatures[i]>temperatures[st.top()]){
                reulst[st.top()]=i-st.top();
                st.pop();
                }
                st.push(i);
            }
        }
        return reulst;
    }
};

LeetCode:496.下一个更大

解法

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        vector<int> result(nums1.size(),-1); //结果数组的长度与1相等
        stack<int> st;
        if(nums1.size()==0) return result;
        unordered_map<int,int> umap;
        //对数组1进行处理 建立哈希表
        for(int i=0;i<nums1.size();i++){
            umap[nums1[i]]=i;
        }
        //用单调栈遍历数组2
        st.push(0);
        for(int i=1;i<nums2.size();i++){
            if(nums2[i]<nums2[st.top()])//小于 等于 都直接入栈
                st.push(i);
            else if(nums2[i]==nums2[st.top()]) 
                st.push(i);
            else{
                //大于栈顶元素 处理结果
                while(!st.empty()&&nums2[i]>nums2[st.top()]){
                    //判断元素是否出现过
                    if(umap.count(nums2[st.top()])>0){
                        int index=umap[nums2[st.top()]];
                        result[index]=nums2[i];
                    }
                    st.pop();
                }
                st.push(i);
            }
        }
        return result;
        }
};

LeetCode:503.下一个更大元素II

用取模的过程模拟成环的遍历

for(i=0;i<nums.size()*2;i++){

i%nums.size()

}

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        vector<int> result(nums.size(),-1);
        stack<int> st;
        st.push(0);//放入第一个元素
        for(int i=1;i<nums.size()*2;i++){
            if(nums[i%nums.size()]<=nums[st.top()]) st.push(i%nums.size());
            else{
                while(!st.empty()&&nums[i%nums.size()]>nums[st.top()]){
                    result[st.top()]=nums[i%nums.size()];
                    st.pop();
                }
                st.push(i%nums.size());
            }
        }
        return result;
    }
};

LeetCode:42.接雨水

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> st;
        st.push(0);
        int sum=0;
        //从1开始遍历所有柱子
        for(int i=1;i<height.size();i++){
            //如果当前遍历的元素(柱子)高度小于栈顶元素的高度,就把这个元素加入栈中,因为栈里本来就要保持从小到大的顺序(从栈头到栈底)
            if(height[i]<height[st.top()]){
                st.push(i);
            }
            //如果当前遍历的元素(柱子)高度等于栈顶元素的高度,要跟更新栈顶元素,因为遇到相相同高度的柱子,需要使用最右边的柱子来计算宽度。
            else if(height[i]==height[st.top()]){
                st.pop();
                st.push(i);
            }
            //如果当前遍历的元素(柱子)高度大于栈顶元素的高度,此时就出现凹槽了
            else{
                while(!st.empty()&&height[i]>height[st.top()]){
                    int mid=height[st.top()];
                    st.pop();
                    if(!st.empty()){
                        int h=min(height[i],height[st.top()])-mid;
                        int w=i-st.top()-1;
                        sum+=h*w;
                    }
                }
                st.push(i);
            }
        }
        return sum;
    }
};

LeetCode:84.柱状图中最大的矩形

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int result=0;
        stack<int> st;
        heights.insert(heights.begin(), 0); // 数组头部加入元素0
        heights.push_back(0); // 数组尾部加入元素0

        st.push(0);
        for(int i=1;i<heights.size();i++){//循环
            //条件1 大于等于的情况
            if(heights[i]>=heights[st.top()]){
                st.push(i);
            }
            //条件2 小于的情况
            else{
                while(!st.empty()&&heights[i]<heights[st.top()]){
                    int mid=st.top();
                    st.pop();
                    if(!st.empty()){
                        int left=st.top();
                        int right=i;
                        int h=heights[mid];
                        int w=right-left-1;
                        result=max(result,w*h);
                    }
                }
                st.push(i);
            }
        }
        return result;
    }
};

感觉是最难理解的一部分了&完结撒花

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值