Skip to content
Related Articles

Related Articles

Sum of minimum elements of all subarrays

View Discussion
Improve Article
Save Article
Like Article
  • Difficulty Level : Hard
  • Last Updated : 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.x
Below is the implementation of above approach 
 

C++




// CPP implementation of above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to return required minimum sum
int 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 program
int 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




// Java implementation of above approach
import 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 sum
static 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 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 PrinciRaj1992

Python3




# Python3 implementation of above approach
 
# Function to return required minimum sum
def 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 Code
if __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#




// C# implementation of above approach
using 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 sum
static 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 Code
public 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

Javascript




<script>
  
// JavaScript implementation of above approach
 
// Function to return required minimum sum
function 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 resultult
document.write( sumSubarrayMins(A, n));
 
 
</script>

Output

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 :

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

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++




// 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 Code
int 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




// Java program to implement the approach
import 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

Python3




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 Code
if __name__ == "__main__":
    A = [3, 1, 2, 4]
    n = len(A)
     
    # function call to get
    # required resultult
    print(sumSubarrayMins(A, n))

Javascript




<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 Code
let A = [3, 1, 2, 4]
let n = A.length
 
// function call to get
// required resultult
document.write(sumSubarrayMins(A, n))
 
// This code is contributed by shinjanpatra
 
</script>

Output

17

  

Time and Space Complexity := O(N)


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!