907. Sum of Subarray Minimums
Given an array of integers
A
, find the sum ofmin(B)
, whereB
ranges over every (contiguous) subarray ofA
.Since the answer may be large, return the answer modulo
10^9 + 7
.
Example 1:
Input: [3,1,2,4]
Output: 17
Explanation: Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4].
Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1. Sum is 17.
Note:
1 <= A.length <= 30000
1 <= A[i] <= 30000
Approach #1: Monotone Stack. [Java]
class Solution {
public int sumSubarrayMins(int[] A) {
int n = A.length;
Stack<int[]> in_stk_p = new Stack<>(), in_stk_n = new Stack<>();
// left is for the distance to previous less element
// right is for the distance to next less element.
int[] left = new int[n], right = new int[n];
for (int i = 0; i < n; ++i) left[i] = i + 1;
for (int i = 0; i < n; ++i) right[i] = n - i; for (int i = 0; i < n; ++i) {
while (!in_stk_p.isEmpty() && in_stk_p.peek()[0] > A[i]) in_stk_p.pop();
left[i] = in_stk_p.isEmpty() ? i + 1 : i - in_stk_p.peek()[1];
in_stk_p.push(new int[] {A[i], i}); while (!in_stk_n.isEmpty() && in_stk_n.peek()[0] > A[i]) {
int[] x = in_stk_n.peek();
in_stk_n.pop();
right[x[1]] = i - x[1];
}
in_stk_n.push(new int[] {A[i], i});
} int res = 0, mod = (int)1e9 + 7;
for (int i = 0; i < n; ++i)
res = (res + A[i]*left[i]*right[i]) % mod; return res;
}
}
Analysis:
Before diving into the solution, we first introduce a very important stack type, which is called momotone stack.
What is monotonous increase stack?
Roughly spkeaking, the elements in the an monotonous increase stack keeps an increasing order.
The typical paradigm for monotonous increase stack:
for(int i = 0; i < A.size(); i++){
while(!in_stk.empty() && in_stk.top() > A[i]){
in_stk.pop();
}
in_stk.push(A[i]);
}.
What can monotonous increase stack do?
(1) find the previous less element of each element in a vector with O(n) time:
What is the previous less element of an element?
For example:
[3, 7, 8, 4]
The previous less element of 7 is 3.
The previous less element of 8 is 7.
The previous less element of 4 is 3.
There are no previous less element for 3.
For simplicity of notation, we use abbreviation PLE to denote Previous Less Element.
C++ code (by slitghly modifying the paradigm):
Instead of directly pushing the element itself, here for simplicity, we push the incex.
We do some record when the index is pushed into the stack.
// previous_less[i] = j means A[j] is the previous less element of A[i].
// previous_less[i] = -1 means there is no previous less element of A[i].
vector<int> previous_less(A.size(), -1);
for(int i = 0; i < A.size(); i++){
while(!in_stk.empty() && A[in_stk.top()] > A[i]){
in_stk.pop();
}
previous_less[i] = in_stk.empty()? -1: in_stk.top();
in_stk.push(i);
}
(2) find the next less element of each element in a vector with O(n) time:
What is the next less element of an element?
For example:
[3, 7, 8, 4]
The next less element of 8 is 4.
The next less element of 7 is 4.
There is no next less element for 3 and 4.
For simplicity of notation, we use abbreviation NLE to denote Next Less Element.
C++ code (by slighly modifying the paradigm):
We do some record when the index is poped out from the stack.
// next_less[i] = j means A[j] is the next less element of A[i].
// next_less[i] = -1 mean there is no next less element of A[i].
vector<int> previous_less(A.size(), -1);
for(int i = 0; i < A.size(); i++){
while(!in_stk.empty() && A[in_stk.top()] > A[i]){
auto x = in_stk.top(); in_stk.pop();
next_less[x] = i;
}
in_stk.push(i);
}
How can the monotonous increase stack be applied to this problem?
For example:
Consider the element 3 in the following vector:
[2, 9, 7, 8, 3, 4, 6, 1]
| |
the previous less the next less
element of 3 element of 3
After finding both NLE and PLE of 3, we can determine the distance between 3 and 2(prevous less), and the distance between 3 and 1(next less). In this example, the distance is 4 and 3 respectively.
How many subarray with 3 being its minimum value?
The answer is 4 * 3.
How much the element 3 contributes to the final answer?
It is 3 * (3 * 4).
What is the final answer?
Denote by left[i] the distance between element A[i] and its PLE.
Denote by right[i] the distance beween element A[i] and its NLE.
The final answer is:
sum(A[i] * left[i] * right[i])
Approach #2: Optimize [C++]
class Solution {
public:
int sumSubarrayMins(vector<int>& A) {
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;
}
};
Analysis:
1. Here we record (A[i], i) in the stack. We can also only record index.
2. For left part and right part, the logic is same.
So for each, we used one stack and one pass.
This process can be optimized to one pass using one stack in total.
Reference:
https://docs.oracle.com/javase/7/docs/api/java/util/Stack.html
907. Sum of Subarray Minimums的更多相关文章
- [LeetCode] 907. Sum of Subarray Minimums 子数组最小值之和
Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarra ...
- 【leetcode】907. Sum of Subarray Minimums
题目如下: 解题思路:我的想法对于数组中任意一个元素,找出其左右两边最近的小于自己的元素.例如[1,3,2,4,5,1],元素2左边比自己小的元素是1,那么大于自己的区间就是[3],右边的区间就是[4 ...
- [Swift]LeetCode907. 子数组的最小值之和 | Sum of Subarray Minimums
Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarra ...
- 子数组最小值的总和 Sum of Subarray Minimums
2018-09-27 23:33:49 问题描述: 问题求解: 方法一.DP(MLE) 动态规划的想法应该是比较容易想到的解法了,因为非常的直观,但是本题的数据规模还是比较大的,如果直接使用动态规划, ...
- leetcode907 Sum of Subarray Minimums
思路: 对于每个数字A[i],使用单调栈找到A[i]作为最小值的所有区间数量,相乘并累加结果.时间复杂度O(n). 实现: class Solution { public: int sumSubarr ...
- LC 918. Maximum Sum Circular Subarray
Given a circular array C of integers represented by A, find the maximum possible sum of a non-empty ...
- 动态规划-Maximum Subarray-Maximum Sum Circular Subarray
2020-02-18 20:57:58 一.Maximum Subarray 经典的动态规划问题. 问题描述: 问题求解: public int maxSubArray(int[] nums) { i ...
- [Swift]LeetCode918. 环形子数组的最大和 | Maximum Sum Circular Subarray
Given a circular array C of integers represented by A, find the maximum possible sum of a non-empty ...
- Maximum Sum Circular Subarray LT918
Given a circular array C of integers represented by A, find the maximum possible sum of a non-empty ...
随机推荐
- 面向对象设计模式纵横谈:Adapter 适配器模式(笔记记录)
适配(转换)的概念无处不在 适配,即在不改变原有实现的基础上,将原先不兼容的接口转换为兼容的接口.生活中适配转换的例子太多了,也是设计模式里面比较容易理解的一个模式. 动机(Motivation) 在 ...
- Banner中文字怎么排版才好看?
今天这命题,相信有很多人提出过疑问,一个好的文字排版会给你的作品增添色彩,我们先看看好的作品是怎样的. 看完这些图大家都能感觉出来这是一个好的作品,大家天生就对美和丑有一定的区分. 其实文字排版也好, ...
- 前后台交互(打开前端页面,不传递任何数据,发送ajax请求)
1.打开前端,不传递任何数据 <script src="./jquery.min.js"></script> <script> $(docume ...
- 获取GUID的GET网址:createguid.com
1.在浏览器的地址栏中输入createguid.com,回车之后即可得到一个GUID 2.在JMeter中可以这样填写HTTP Request 然后通过正则表达式提取器提取GUID <texta ...
- web札记
url中不能是#号,struts不读取#之后的字符串.
- jquery validate 之多tab页同时校验问题
1.设置多tab页同时校验: $("form").validate({ignore: ":hidden", ignore: ""}); 由于 ...
- 向一个文件流写入一个数据块---fwrite
函数原型:int fwrite(const void *buffer,size_t size,size_t count,FILE *stream); 参数说明:buffer:用于写入到文件的数据地址. ...
- 关于adbd进程的ROOT权限问题
http://blog.csdn.net/a345017062/article/details/6254402 adbd源码位于system/core/adb/目录下,可执行文件位于/sbin/adb ...
- Linux下timer延时的使用
http://blog.csdn.net/hzpeterchen/article/details/8090385 因笔者工作在嵌入式平台上(非x386),下面给出的结论仅在arm平台上测试过. 1. ...
- flask_模板
由于python中生成html比较繁琐,所以flask自动为你配置好jinjia2模板.下面我们开始学习模板应用吧~ 1.编写microblog模块 注:(1)这里为了渲染模板,我们从Flask导入了 ...