leetcode 907

907 子数组的最小值之和

给定一个整数数组 A,找到 min(B) 的总和,其中 B 的范围为 A 的每个(连续)子数组。

由于答案可能很大,因此返回答案模 10^9 + 7。

示例:

输入:[3,1,2,4]
输出:17
解释:
子数组为 [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4]。 
最小值为 3,1,2,4,1,1,2,1,1,1,和为 17。

详细解答:

这道题看起来很简单,便利整个数组记录最小值似乎就可以完成,我第一次就是这样做的,结果就是超时,明显就是不能暴力解决问题,要用巧,此题怎么用巧呢,请耐心看下面详细分解。

我们假设 数组A={3,1,2,4,5,0,7,8};

我们用栈记录记录上次访问到最小值的下标。其实不用栈也行,只要记住最小值的下标就行;

假如上次遍历到的最小值为1,下标是1,

当我们遍历到0时,1的右边数组{1,2,4,5},{1,2,4},{1,2},{1}这些子数组的最小值都是0,总数为0的下标-1的下标=5-1=4

再加上{3,1},(上上一次最小值3的下标与上一次最小值1的下标之间的距离就是左边的次数)

total=left×right;

为了遍历到每一个点,我们必须在数组后添加一个0;

因此我们的解题代码如下;

class Solution {
public:
     int sumSubarrayMins(vector<int>& A) {
        stack<int> s;
        int size = A.size(), sum = 0, mod = 1e9 +7;
        A.push_back(0);
        for(int i = 0; i <= size; i++){
            while(!s.empty() && A[i] < A[s.top()]){
                int j = s.top();
                s.pop();
                int left = j - (s.empty() ? -1 : s.top());
                sum = (sum + left * (i - j) * A[j]) % mod;
            }
            s.push(i);
        }
        return sum;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值