Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarray of A.

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. 1 <= A.length <= 30000
  2. 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://leetcode.com/problems/sum-of-subarray-minimums/discuss/170750/C%2B%2BJavaPython-Stack-Solution

https://docs.oracle.com/javase/7/docs/api/java/util/Stack.html

https://leetcode.com/problems/sum-of-subarray-minimums/discuss/178876/stack-solution-with-very-detailed-explanation-step-by-step

907. Sum of Subarray Minimums的更多相关文章

  1. [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 ...

  2. 【leetcode】907. Sum of Subarray Minimums

    题目如下: 解题思路:我的想法对于数组中任意一个元素,找出其左右两边最近的小于自己的元素.例如[1,3,2,4,5,1],元素2左边比自己小的元素是1,那么大于自己的区间就是[3],右边的区间就是[4 ...

  3. [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 ...

  4. 子数组最小值的总和 Sum of Subarray Minimums

    2018-09-27 23:33:49 问题描述: 问题求解: 方法一.DP(MLE) 动态规划的想法应该是比较容易想到的解法了,因为非常的直观,但是本题的数据规模还是比较大的,如果直接使用动态规划, ...

  5. leetcode907 Sum of Subarray Minimums

    思路: 对于每个数字A[i],使用单调栈找到A[i]作为最小值的所有区间数量,相乘并累加结果.时间复杂度O(n). 实现: class Solution { public: int sumSubarr ...

  6. 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 ...

  7. 动态规划-Maximum Subarray-Maximum Sum Circular Subarray

    2020-02-18 20:57:58 一.Maximum Subarray 经典的动态规划问题. 问题描述: 问题求解: public int maxSubArray(int[] nums) { i ...

  8. [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 ...

  9. Maximum Sum Circular Subarray LT918

    Given a circular array C of integers represented by A, find the maximum possible sum of a non-empty ...

随机推荐

  1. springmvc中@RequestMapping的使用

    通过RequestMapping注解可以定义不同的处理器映射规则. 1.1 URL路径映射 @RequestMapping(value="/item")或@RequestMappi ...

  2. C语言字符串操作函数实现

    1.字符串反转 – strRev void strRev(char *str) { assert(NULL != str);   int length=strlen(str); ; while(end ...

  3. ubuntu下设置DNS服务器

    当网卡通过DHCP获取IP地址时,DHCP会根据DHCP服务器配置,自动给系统分配DNS服务器地址,此时执行 ping www.baidu.com 动作,会将百度的域名在本地转换成ip地址,然后走路由 ...

  4. oracle两个客户端路径记录

    32 C:\WINDOWS\assembly\GAC_64\Oracle.DataAccess\2.112.3.0__89b483f429c4734264 C:\WINDOWS\Microsoft.N ...

  5. 通过程序修改注册表键值来达到修改IE配置参数的目的

    通过程序修改注册表键值来达到修改IE配置参数的目的 使用IE访问应用程序或网页时经常需要设置一些选项(工具-Internet 选项),比如为了避免缓存网页,把工具-Internet选项-常规选项卡-I ...

  6. 第1章 (名词)Le nom

    ★名词的种类:(1)普通名词 —专有名词,如:          un livre —la Chine(2)可数名词—不可数名词,如:          un ami —le lait(3)具体名词— ...

  7. 第一章:模型层model layer

    1.模型和字段 (1)基本的原则如下: 每个模型在Django中的存在形式为一个Python类 每个模型都是django.db.models.Model的子类 模型的每个字段(属性)代表数据表的某一列 ...

  8. 20155218 2016-2017-2 《Java程序设计》第10周学习总结

    20155218 2016-2017-2 <Java程序设计>第10周学习总结 教材学习内容总结 一个IP地址可以对应多个域名,一个域名只能对应一个IP地址. 在网络通讯中,第一次主动发起 ...

  9. 使用ASI传递post表单..参数是数组

    你可以使用addPostValue方法来发送相同name的多个数据(梦维:服务端会以数组方式呈现): ASIFormDataRequest *request = [ASIFormDataRequest ...

  10. day02(继承,重写,this,super,final,抽象类)

    继承 概述:日常生活中儿女总会继承长辈的遗产,java语言也是.通过继承多种实物之间形成一种关系. 特点: ①一个类只能继承一个父类 ②一个父类可以有多个子类 ③可以多层继承(a类继承b类   C类继 ...