题解 | 子数组的最小值之和

子数组的最小值之和

https://www.nowcoder.com/practice/a7401d0dd4ec4071a31fd434e150bcc2

class Solution {
public:
    //对于数组中的一个数,看他的左边有多少大于他的数,右边有多少大于它的数,两个值相乘,即以本值为最小值的连续子树组的个数,
    //要找到最近的小于它的数,使用栈,递增栈,保留的是局部最小值,只用比较局部最小值即可;数组记录全局最小值;
    int sumSubarr(vector<int>& nums) {
        const int MOD = 1e9 + 7;
        int n = nums.size();

        stack<int> stk;
        vector<int> left(n);
        vector<int> right(n);

        for(int i=0; i<=n-1; ++i){
            while(!stk.empty() && nums[stk.top()] > nums[i]){ //这里把大于它的数去掉,保留了等于,防止左边扩张重复;
                stk.pop();
            }
            if(stk.empty())left[i] = i+1;
            else left[i] = i - stk.top();

            stk.push(i);
        }

        stk = stack<int>();

        for(int i=n-1; i>=0; --i){
            while(!stk.empty() && nums[stk.top()] >=nums[i]){ //这里把等于它的数也去掉了,因为左边已经限制了相同数的范围,即左边是不交叉覆盖的连续子数组,右边可以交叉覆盖,结果也是不同的子数组;
                stk.pop();
            }
            right[i] = stk.empty()? n-i : stk.top() - i;
            stk.push(i);
        }

        long long res = 0;
        for(int i=0; i<n; ++i){
            res = (res + (long long)nums[i]*left[i]*right[i] ) % MOD;
        }

        return res;
    }
};

全部评论

相关推荐

代码飞升:别用口语,后端就写后端,前端就写前端,最后别光后悔
点赞 评论 收藏
分享
06-02 15:53
阳光学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务