907. Sum of Subarray Minimums
Given an array of integers
A, find the sum ofmin(B), whereBranges 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 <= 300001 <= 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 ...
随机推荐
- Restful API设计要点
1 Restful API时面向资源,不能面向动作: 2 充分利用http协议的GET, HEAD, OPTION, PUT, POST, DELETE几种方法: 3 GET方法用于获取资源,是幂等和 ...
- PAT 1069 微博转发抽奖(20)(代码+思路+测试点4)
1069 微博转发抽奖(20 分) 小明 PAT 考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔 N 个人就发出一个红包.请你编写程序帮助他确定中奖名单. 输入格式: 输入第一行 ...
- [freeCodeCamp] solution to HTTP JSON API SERVER passed!
var http = require('http') var url = require('url') function parsetime (time) { return { hour: time. ...
- VisulaVM 性能:分析 JVM 性能的免费工具
VisualVM是一个集成多个JDK命令行工具的可视化工具.可以作为Java应用程序性能分析和运行监控的工具.开发人员可以利用它来监控.分 析线程信息,浏览内存堆数据.系统管理员可以利用它来监测.控制 ...
- laravel数据库操作
一.配置文件路径:/.env DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT= DB_DATABASE=test DB_USERNAME=root DB_P ...
- Laravel Nginx 站点配置文件(Homestead)
server { listen 80; listen 443 ssl http2; server_name fmtmis.local; root "/home ...
- oracle 表分区例子
oracle表分区详解-一步一步教你oracle分区表详解 .创建三个不同的表空间,模拟在不同磁盘上的保存不同范围的数据 create tablespace test01 datafile ...
- 数据库链接 mybatis spring data jpa 两种方式
jdbc mybatis spring data jpa dao service webservice jaxrs jaxws springmvc w ...
- centos6.5 设置ssh无密码登录
:关闭防火墙 vim /etc/selinux/config 把SELINUX=enforcing修改为SELINUX=disabled A机器root连接B机器root用户 (root用户登录) ...
- jquery统计显示或隐藏的元素个数
统计显示的checkbox的数量: 统计隐藏的checkbox数量: