Sum of minimum elements of all subarrays

04 Jul, 2022
Given an array A of n integers. The task is to find the sum of minimum of all possible (contiguous) subarray of A.Examples:  
Input: A = [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.Input : A = [1, 2, 3, 4] Output : 20
 
Approach: The Naive approach is to generate all possible (contiguous) subarrays, find their minimum and add them to result. The time complexity will be O(N2).Efficient Approach: The general intuition for solution to the problem is to find sum(A[i] * f(i)), where f(i) is the number of subarrays in which A[i] is the minimum.In order to find f[i], we need to find out: left[i], the length of strictly larger numbers on the left of A[i], right[i], the length of larger numbers on the right of A[i].We make two arrays left[ ] and right[ ] such that: left[i] + 1 equals to the number of subarrays ending with A[i], and A[i] is only single minimum. Similarly, right[i] + 1 equals to the number of subarrays starting with A[i], and A[i] is first minimum.Finally, f(i) = (left[i]) * (right[i]), where f[i] equals total number of subarrays in which A[i] is minimum.xBelow is the implementation of above approach  
C++
Java
Python3
C#
Javascript
// CPP implementation of above approach#include <bits/stdc++.h>using namespace std; // Function to return required minimum sumint sumSubarrayMins(int A[], int n){    int left[n], right[n];     stack<pair<int, int> > s1, s2;     // getting number of element strictly larger    // than A[i] on Left.    for (int i = 0; i < n; ++i) {        int cnt = 1;         // get elements from stack until element        // greater than A[i] found        while (!s1.empty() && (s1.top().first) > A[i]) {            cnt += s1.top().second;            s1.pop();        }         s1.push({ A[i], cnt });        left[i] = cnt;    }     // getting number of element larger than A[i] on Right.    for (int i = n - 1; i >= 0; --i) {        int cnt = 1;         // get elements from stack until element greater        // or equal to A[i] found        while (!s2.empty() && (s2.top().first) >= A[i]) {            cnt += s2.top().second;            s2.pop();        }         s2.push({ A[i], cnt });        right[i] = cnt;    }     int result = 0;     // calculating required resultult    for (int i = 0; i < n; ++i)        result = (result + A[i] * left[i] * right[i]);     return result;} // Driver programint main(){    int A[] = { 3, 1, 2, 4 };     int n = sizeof(A) / sizeof(A[0]);     // function call to get required resultult    cout << sumSubarrayMins(A, n);     return 0;}// This code is written by Sanjit_Prasad
// Java implementation of above approachimport java.util.*; class GFG{static class pair{    int first, second;    public pair(int first, int second)    {        this.first = first;        this.second = second;    }} // Function to return required minimum sumstatic int sumSubarrayMins(int A[], int n){    int []left = new int[n];    int []right = new int[n];     Stack<pair> s1 = new Stack<pair>();    Stack<pair> s2 = new Stack<pair>();         // getting number of element strictly larger    // than A[i] on Left.    for (int i = 0; i < n; ++i)    {        int cnt = 1;         // get elements from stack until element        // greater than A[i] found        while (!s1.isEmpty() &&               (s1.peek().first) > A[i])        {            cnt += s1.peek().second;            s1.pop();        }         s1.push(new pair(A[i], cnt));        left[i] = cnt;    }     // getting number of element larger    // than A[i] on Right.    for (int i = n - 1; i >= 0; --i)    {        int cnt = 1;         // get elements from stack until element        // greater or equal to A[i] found        while (!s2.isEmpty() &&               (s2.peek().first) >= A[i])        {            cnt += s2.peek().second;            s2.pop();        }         s2.push(new pair(A[i], cnt));        right[i] = cnt;    }     int result = 0;     // calculating required resultult    for (int i = 0; i < n; ++i)        result = (result + A[i] * left[i] *                                  right[i]);     return result;} // Driver Codepublic static void main(String[] args){    int A[] = { 3, 1, 2, 4 };     int n = A.length;     // function call to get required result    System.out.println(sumSubarrayMins(A, n));}} // This code is contributed by PrinciRaj1992
# Python3 implementation of above approach # Function to return required minimum sumdef sumSubarrayMins(A, n):     left, right = [None] * n, [None] * n         # Use list as stack    s1, s2 = [], []     # getting number of element strictly    # larger than A[i] on Left.    for i in range(0, n):        cnt = 1         # get elements from stack until        # element greater than A[i] found        while len(s1) > 0 and s1[-1][0] > A[i]:            cnt += s1[-1][1]            s1.pop()         s1.append([A[i], cnt])        left[i] = cnt     # getting number of element    # larger than A[i] on Right.    for i in range(n - 1, -1, -1):        cnt = 1         # get elements from stack until        # element greater or equal to A[i] found        while len(s2) > 0 and s2[-1][0] >= A[i]:            cnt += s2[-1][1]            s2.pop()         s2.append([A[i], cnt])        right[i] = cnt     result = 0     # calculating required resultult    for i in range(0, n):        result += A[i] * left[i] * right[i]     return result # Driver Codeif __name__ == "__main__":     A = [3, 1, 2, 4]    n = len(A)     # function call to get    # required resultult    print(sumSubarrayMins(A, n)) # This code is contributed# by Rituraj Jain
// C# implementation of above approachusing System;using System.Collections.Generic; class GFG{public class pair{    public int first, second;    public pair(int first, int second)    {        this.first = first;        this.second = second;    }} // Function to return required minimum sumstatic int sumSubarrayMins(int []A, int n){    int []left = new int[n];    int []right = new int[n];     Stack<pair> s1 = new Stack<pair>();    Stack<pair> s2 = new Stack<pair>();         // getting number of element strictly larger    // than A[i] on Left.    for (int i = 0; i < n; ++i)    {        int cnt = 1;         // get elements from stack until element        // greater than A[i] found        while (s1.Count!=0 &&            (s1.Peek().first) > A[i])        {            cnt += s1.Peek().second;            s1.Pop();        }         s1.Push(new pair(A[i], cnt));        left[i] = cnt;    }     // getting number of element larger    // than A[i] on Right.    for (int i = n - 1; i >= 0; --i)    {        int cnt = 1;         // get elements from stack until element        // greater or equal to A[i] found        while (s2.Count != 0 &&              (s2.Peek().first) >= A[i])        {            cnt += s2.Peek().second;            s2.Pop();        }         s2.Push(new pair(A[i], cnt));        right[i] = cnt;    }     int result = 0;     // calculating required resultult    for (int i = 0; i < n; ++i)        result = (result + A[i] * left[i] *                                  right[i]);     return result;} // Driver Codepublic static void Main(String[] args){    int []A = { 3, 1, 2, 4 };     int n = A.Length;     // function call to get required result    Console.WriteLine(sumSubarrayMins(A, n));}} // This code is contributed by Rajput-Ji
<script>  // JavaScript implementation of above approach // Function to return required minimum sumfunction sumSubarrayMins(A, n){    var left = Array(n), right = Array(n);     var s1 = [], s2 = [];     // getting number of element strictly larger    // than A[i] on Left.    for (var i = 0; i < n; ++i) {        var cnt = 1;         // get elements from stack until element        // greater than A[i] found        while (s1.length!=0 && (s1[s1.length-1][0]) > A[i]) {            cnt += s1[s1.length-1][1];            s1.pop();        }         s1.push([A[i], cnt]);        left[i] = cnt;    }     // getting number of element larger than A[i] on Right.    for (var i = n - 1; i >= 0; --i) {        var cnt = 1;         // get elements from stack until element greater        // or equal to A[i] found        while (s2.length!=0 && (s2[s2.length-1][0]) >= A[i]) {            cnt += s2[s2.length-1][1];            s2.pop();        }         s2.push([A[i], cnt]);        right[i] = cnt;    }     var result = 0;     // calculating required resultult    for (var i = 0; i < n; ++i)        result = (result + A[i] * left[i] * right[i]);     return result;} // Driver program var A = [3, 1, 2, 4];var n = A.length; // function call to get required resultultdocument.write( sumSubarrayMins(A, n));  </script>
17
Time Complexity: O(N), where N is the length of A. Space Complexity: O(N).
Another Approach : 
It is a dynamic programming approach. 
First, calculate the next smaller element index on the right side for each index using stacks.
At any index i, dp[i] denotes the total sum of all the sub-arrays starting from index i. 
For calculating the answer for each index, there will be two cases :
The current element is the smallest element amongst all the elements on the right-hand side. So ans will be (( range of curr_index *  arr[curr_index] )) . As it will be the smallest element in all the sub-arrays starting from  curr_index.
The current element is the smallest element amongst all the elements on the right-hand side. So ans will be (( range of curr_index *  arr[curr_index] )) . As it will be the smallest element in all the sub-arrays starting from  curr_index.
There is an element present on right, which is smaller than the current element. Answer from that smaller_element is already stored in dp. Just Calculate the answer from current_index to smaller_right_index.upto_smaller = (right_index – curr_index)*arr[curr_index]     ## sum up to right smaller index form curr_index .curr_sum = upto_smaller + dp[right_index]
upto_smaller = (right_index – curr_index)*arr[curr_index]     ## sum up to right smaller index form curr_index .
curr_sum = upto_smaller + dp[right_index]
Finally , return the sum(dp).
For eg :- arr = [4,3,6]
dp[6] = 6
dp[3] => (3-1)*3 => 6     #smallest element
dp[4] = (1 -0) *(4) + dp[3]  => 4 + 6 => 10
Final answer = 6 + 6 + 10= 22
C++
Java
Python3
Javascript
// C++ program to implement the approach#include <bits/stdc++.h> using namespace std; int sumSubarrayMins(int arr[], int n){    int dp[n];    for (int i = 0; i < n; i++)        dp[i] = 0;     // calculate right smaller element    int right[n];     for (int i = 0; i < n; i++) {        right[i] = i;    }    vector<int> stack{ 0 };     for (int i = 1; i < n; i++) {         int curr = arr[i];        while ((stack.size() > 0)               && (curr < arr[stack.back()])) {             int idx = stack.back();            stack.pop_back();            right[idx] = i;        }        stack.push_back(i);    }     dp[n - 1] = arr[n - 1];     for (int i = n - 2; i >= 0; i--) {         int right_idx = right[i];        if (right_idx == i) { // case 1             int curr = (n - i) * arr[i];            dp[i] = curr;        }         else { // case 2             // sum upto next smaller rhs element            int upto_small = (right_idx - i) * (arr[i]);             int curr_sum = (upto_small + dp[right_idx]);            dp[i] = curr_sum;        }    }           //calculating sum of dp    int sum = 0;    sum = accumulate(dp, dp + n, sum);    return sum;} // Driver Codeint main(){    int A[] = { 3, 1, 2, 4 };    int n = sizeof(A) / sizeof(A[0]);     // function call to get    // required result    cout << sumSubarrayMins(A, n) << endl;} // This code is contributed by phasing17
// Java program to implement the approachimport java.util.*; public class GFG {   static int sumSubarrayMins(int[] arr, int n)  {    int dp[] = new int[n];    for (int i = 0; i < n; i++)      dp[i] = 0;     // calculate right smaller element    int right[] = new int[n];     for (int i = 0; i < n; i++) {      right[i] = i;    }    ArrayList<Integer> stack = new ArrayList<Integer>();    stack.add(0);     for (int i = 1; i < n; i++) {       int curr = arr[i];      while (        (stack.size() > 0)        && (curr            < arr[stack.get(stack.size() - 1)])) {         int idx = stack.get(stack.size() - 1);        stack.remove(stack.size() - 1);        right[idx] = i;      }      stack.add(i);    }     dp[n - 1] = arr[n - 1];     for (int i = n - 2; i >= 0; i--) {       int right_idx = right[i];      if (right_idx == i) { // case 1         int curr = (n - i) * arr[i];        dp[i] = curr;      }       else { // case 2         // sum upto next smaller rhs element        int upto_small = (right_idx - i) * (arr[i]);         int curr_sum = (upto_small + dp[right_idx]);        dp[i] = curr_sum;      }    }     // calculating sum of dp    int sum = 0;     for (int i = 0; i < dp.length; i++)      sum += dp[i];     return sum;  }   // Driver Code  public static void main(String[] args)  {    int A[] = { 3, 1, 2, 4 };    int n = A.length;     // function call to get    // required result    System.out.println(sumSubarrayMins(A, n));  }} // This code is contributed by phasing17
def sumSubarrayMins(arr, n):         dp = [0]*(n)         # calculate right smaller element    right = [i for i in range(n)]     stack = [0]     for i in range(1,n,1):         curr = arr[i]        while(stack and curr < arr[stack[-1]]):             idx = stack.pop()            right[idx] = i         stack.append(i)     dp[-1] = arr[-1]     for i in range(n-2,-1,-1):         right_idx = right[i]            if right_idx == i:     # case 1             curr = (n-i)*arr[i]            dp[i] = curr         else:   # case 2                       # sum upto next smaller rhs element            upto_small = (right_idx-i)*(arr[i])                           curr_sum = (upto_small + dp[right_idx])            dp[i] = curr_sum     return (sum(dp))          # Driver Codeif __name__ == "__main__":    A = [3, 1, 2, 4]    n = len(A)         # function call to get    # required resultult    print(sumSubarrayMins(A, n))
<script> function sumSubarrayMins(arr, n){         let dp = new Array(n).fill(0)         // calculate right smaller element    let right = new Array(n);    for(let i = 0; i < n; i++)    {        right[i] = i;    }    let stack = [0]     for(let i = 1; i < n; i++){         let curr = arr[i]        while(stack && curr < arr[stack[stack.length-1]]){             let idx = stack.shift()            right[idx] = i        }        stack.push(i)    }    dp[dp.length - 1] = arr[arr.length - 1]     for(let i = n - 2; i >= 0; i--){         let right_idx = right[i]            if(right_idx == i){     // case 1             let curr = (n - i)*arr[i]            dp[i] = curr        }         else{   // case 2                       // sum upto next smaller rhs element            let upto_small = (right_idx-i)*(arr[i])                           let curr_sum = (upto_small + dp[right_idx])            dp[i] = curr_sum        }     }         let sum = 0    for(let i of dp){        sum += i    }    return sum }     // Driver Codelet A = [3, 1, 2, 4]let n = A.length // function call to get// required resultultdocument.write(sumSubarrayMins(A, n)) // This code is contributed by shinjanpatra </script>
17
  
Time and Space Complexity := O(N)
rituraj_jain
princiraj1992
Rajput-Ji
swapnilghule
rutvik_56
chantya17
shinjanpatra
phasing17
subarray
subarray-sum
Arrays
Mathematical
Stack
Arrays
Mathematical
Stack
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.