NC386 子数组的最小值之和

子数组的最小值之和

https://www.nowcoder.com/practice/a7401d0dd4ec4071a31fd434e150bcc2?tpId=196&tqId=40517&rp=1&ru=/exam/oj&qru=/exam/oj&sourceUrl=%2Fexam%2Foj&difficulty=undefined&judgeStatus=undefined&tags=581&title=

思路: alt

class Solution {
public:
    int sumSubarr(vector<int>& nums) {
        int n=nums.size();
        long ans=0;
        //leftmin用于存每个元素左边第一个小于本身的元素的位置
        //rightmin用于存每个元素右边第一个小于等于本身的元素的位置
        vector<int>leftmin(n,-1);
        vector<int>rightmin(n,n);
        //进行取余10^9+7
        const int M=1000000007;
        //用单调栈维护
        stack<int>stack1;
        //正向遍历找到每个元素左边第一个小于等于本身的元素的位置,
        //但是记录的时候就反着记:记每个元素右边第一个小于等于本身的元素的位置
        for(int i=0;i<n;i++){
            while(!stack1.empty()&&nums[stack1.top()]>nums[i]){
                rightmin[stack1.top()]=i;
                stack1.pop();
            }
            stack1.push(i);
        }
        //调用无参构造函数将栈清空
        stack1=stack<int>();
        //反向遍历找到右边第一个小于本身的元素的位置
        for(int i=n-1;i>=0;i--){
            while(!stack1.empty()&&nums[stack1.top()]>=nums[i]){
                leftmin[stack1.top()]=i;
                stack1.pop();
            }
            stack1.push(i);
        }
        //推导出来的公式:以nums[i]为最小元素的区间个数时left[i]*right[i]
        //所以以nums[i]为最小元素之和是:nums[i]*left[i]*right[i]
        for(int i=0;i<n;i++){
            int l=leftmin[i];
            int r=rightmin[i];
            ans+=(long)((r-i)*(i-l)%M)*nums[i]%M;
        }
        return ans%M;
    }
};
全部评论

相关推荐

11-28 17:58
门头沟学院 Java
美团 JAVA开发 n×15.5
牛客786276759号:百度现在晋升很难的 而且云这块的业务没美团好 你看百度股价都跌成啥样了
点赞 评论 收藏
分享
11-27 12:36
已编辑
门头沟学院 前端工程师
Apries:这个阶段来说,很厉害很厉害了,不过写的简历确实不是很行,优势删掉吧,其他的还行
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-26 15:46
已编辑
字节国际 电商后端 24k-35k
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务