算法训练营day59_单调栈(3.24提前打)

算法训练营day59_单调栈(3.24提前打)

503.下一个更大元素II

两个数组拼接到一起;(vector用insert插入,不能直接赋值,因为大小规定了,会越界,要是数组的话,提前开够了空间,不会越界)

从后往前走一遍单调栈;

class Solution {
public:
    int stk[10010],top;
    vector<int> nextGreaterElements(vector<int>& nums) {
        memset(stk,0,sizeof stk);
        top=0;

        int n=nums.size();
        vector<int> t(nums.begin(),nums.end());
        nums.insert(nums.end(),t.begin(),t.end());
        vector<int> ans(n,-1);

        for(int i=n*2-1;i>=0;i--){
            while(top&&nums[i]>=stk[top]) top--;
            if(i<n){
                if(top) ans[i]=stk[top];
            }
            stk[++top]=nums[i];
        }

        return ans;
    }
};

42.接雨水

dp预处理

没用单调栈的思路,没想出来;

这道题就是对于每个柱子,找出左边最大的与右边最大的,取小值,再减去当前柱子高度就是当前柱子的贡献值;

需要注意的是,左边与右边都包括自己,这样的话就算找不到比自己大的,也会自己-自己,贡献值为0;

一个小dp预处理出来i左边最大值的数组,i右边最大的数组;然后直接遍历累加贡献值;

class Solution {
public:
    int lh[20010],rh[20010];
    int trap(vector<int>& height) {
        memset(lh,0,sizeof lh);
        memset(rh,0,sizeof rh);
        int n=height.size();
        
        for(int i=1;i<=n;i++){
            lh[i]=max(height[i-1],lh[i-1]);
        }
        for(int i=n;i>=1;i--){
            rh[i]=max(height[i-1],rh[i+1]);
        }

        int ans=0;
        for(int i=0;i<n;i++){
            ans+=min(lh[i+1],rh[i+1])-height[i];
        }
        return ans;
    }
};

单调栈

凹槽才会存水,如果是连着递减,那么不会存水,遇到了一个大的,往前依次清算;所以用到了单调栈;

维护一个单调递减的单调栈,遇到一个大的,往前看;

当前栈顶是凹的部分,当前栈顶左边右边都比它大,计算(min(左右高度)-当前高度)*(距离),这个计算的就是当前高度上面能存的雨水;

与动归遍历一下子加一列不同,这里一下子加几排;

要注意的是,最后栈里只有一个元素的时候,就不能算了,因为它没有左边的,不是凹槽,存不了水;

class Solution {
public:
    int stk[20010],cnt;
    int trap(vector<int>& height) {
        memset(stk,0,sizeof stk);
        cnt=0;
        
        int ans=0;
        int n=height.size();
        for(int i=0;i<n;i++){
            while(cnt&&height[i]>height[stk[cnt]]){
                int cur=stk[cnt];
                cnt--;
                if(!cnt) break;
                int l=stk[cnt];
                int h=min(height[l],height[i])-height[cur];
                int k=(i-l-1);
                ans+=h*k;
            }
            stk[++cnt]=i;
        }
        return ans;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值