1)题目
子数组的最小值之和
要求:
给定一个整数数组 A,找到 min(B) 的总和,其中 B 的范围为 A 的每个(连续)子数组。
样例
输入:[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。
2)思路
单调栈解决;
假设从数组的头部遍历,如果后面的数大于前面的数,那么这两个数构成的子数组取得肯定是前面的小的数;
如果后面的数小于前面的数,那么子数组就得取后面的数。
那么当前元素的贡献就是:
A[i] * A[i]与其前一个较少的元素之间的距离 * A[i]A[i]与其下一个较小元素之间的距离
将所有元素的贡献相加即可。
3)代码
//头文件
#pragma once
#include <iostream>
using namespace std;
#include <stack>
class Solution {
public:
/**
* @param A: an array
* @return: the sum of subarray minimums
*/
int sumSubarrayMins(vector<int> &A) {
// Write your code here.
int res = 0, n = A.size(), mod = 1e9 + 7, j, k;
stack<int> s;
for (int i = 0; i <= n; ++i) {
while (!s.empty() && A[s.top()] > (i == n ? 0 : A[i])) {
j = s.top(), s.pop();
k = s.empty() ? -1 : s.top();
res = (res + A[j] * (i - j) * (j - k)) % mod;
}
s.push(i);
}
return res;
}
};