Leetcode 907 Sum of Subarray Minimums article[官方文章翻译]

题目描述:

给定一个数组A,视B为A的子序列,找到所有子序列中最小数字的和,并相加。

若数字特别大,则将该数对10^9+7取模

Example 1:

input: [3,1,2,4]

output: 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 。

官方文章网址:https://leetcode.com/articles/sum-of-subarray-minimums/

手段2:单调栈

直觉:

For a specific j, let's try to count the minimum of each subarray [i, j]. The intuition is that as we increment j++, these minimums may be related to each other. Indeed, min(A[i:j+1]) = min(A[i:j], A[j+1]).

对于特定的j,让我们去计算每个子数组[i,j]的最小值。直觉就是我们让j不断地递增,这些最小值可能互相有关,实际上在数组中,i到j+1的最小值实际上就是i到j的最小值j+1比较,而这个步骤。(正是这个表达式,产生了使用单调栈的思想)

Playing with some array like A = [1,7,5,2,4,3,9], with j = 6 the minimum of each subarray [i, j] is B = [1,2,2,2,3,3,9]. We can see that there are critical points i = 0, i = 3, i = 5, i = 6 where a minimum is reached for the first time when walking left from j.

让我们假定一个数组像 A = [1,7,5,2,4,3,9],当j = 6时,从i开始最小的数分别是B = [1,2,2,3,3,9],我们可以看到,当从j向左走时,存在临界点i=0,i=3,i=5,i=6,其中第一次达到最小值。

算法:

Let's try to maintain an RLE (run length encoding) of these critical points B. More specifically, for the above (A, j), we will maintain stack = [(val=1, count=1), (val=2, count=3), (val=3, count=2), (val=9, count=1)], that represents a run length encoding of the subarray minimums B = [1,2,2,2,3,3,9]. For each j, we want sum(B).

让我们尝试处理这些临界点B的RLE(行程编码),更具体的来说,对于上面的(A,j),我们实施一个栈,这个栈在上面的例子中,会变成这样: [(val=1, count=1), (val=2, count=3), (val=3, count=2), (val=9, count=1)]。

As we increment j, we will have to update this stack to include the newest element (val=x, count=1). We need to pop off all values >= x before, as the minimum of the associated subarray [i, j] will now be A[j] instead of what it was before.

当我们递增j时,我们将不得不更新这个栈及最新元素,我们需要把所有比A[j]大或等于的值弹出栈,让这个栈控制在最小值得控制下,同时每弹出一个,count就增加,直到新元素入栈,count重置为1。

At the end, the answer is the dot product of this stack: ∑e ∈ stacke.val∗e.counte ∈ stack∑​e.val∗e.count, which we also maintain on the side as the variable dot.

最后,答案就是栈的点积之和。

C++代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stack>
using namespace std;
int mod = pow(10,9)+7;
int sumSubarrayMins(vector<int>& A) {
    int MOD = 1000000007;
    
    stack<pair<int,int>> stack;
    int ans = 0, dot = 0;
    for (int j = 0; j < A.size(); ++j) {
        // Add all answers for subarrays [i, j], i <= j
        int count = 1;
        if(!stack.empty())
        while (!stack.empty() && stack.top().first >= A[j]) {
            pair<int,int> node = stack.top();
            stack.pop();
            count += node.second;
            dot -= node.first * node.second;
        }
        stack.push(make_pair(A[j], count));
        dot += A[j] * count;
        ans += dot;
        ans %= MOD;
    }
    
    return ans;
}
int main()
{
    vector<int>v;
    v.push_back(3);
    v.push_back(1);
    v.push_back(2);
    v.push_back(4);
    cout<<sumSubarrayMins(v)<<endl;
    
}

猜你喜欢

转载自blog.csdn.net/narcissus2_/article/details/82969473