Sum of minimum elements of all possible sub-arrays of an array
Given an array arr[], the task is to find the sum of the minimum elements of every possible sub-array of the array.
Examples:
Input: arr[] = {1, 3, 2}
Output: 15
All possible sub-arrays are {1}, {2}, {3}, {1, 3}, {3, 2} and {1, 3, 2}
And, the sum of all the minimum elements is 1 + 2 + 3 + 1 + 2 + 1 = 10
Input: arr[] = {3, 1}
Output: 5
A simple method is to generate all the sub-arrays and then sum the minimum elements in all of them. The time complexity of this solution will be O(n3).
Better method: The key for optimization is the question:
In how many segments, the value at an index will be minimum?
The next idea that might come into our mind will be for every index i in the array arr, we try to find:
Left count: We iterate towards the left of the index i till we don’t encounter an element strictly lesser than arr[i] or we don’t reach the left end of the array. Let us call this count for the index i of the given array as CLi.
Right count: We iterate towards the right of the index till we don’t encounter an element less than or equal to the value at the index, or we don’t reach the right end. Let us call this count for the index i of the given array as CRi.
(CLi + 1) * (CRi + 1) will be the number of sub-arrays for the current index i in which its value will be minimal because there are CLi + 1 ways to choose elements from the left side (including choosing no element) and CRi + 1 ways to choose elements from the right side.
The time complexity of this approach will be O(n2)
The Best method:
This problem can be solved using a stack data structure in O(n) time. The idea remains the same as is in the previous approach. For the sake of saving some time, we will use a stack from the Standard Template Library of C++.
Left count: Let CLi represent the left count for an index i. CLi for an index i can be defined as the number of elements between the index i and the right most element whose value is strictly less than arr[i] having index less than i. If, there is no such element, then CLi for an element will be equal to the number of elements to the left of the index i.
To achieve this, we will insert only the index of the elements from left to right into the stack. Let us suppose, we are inserting an index i in the stack and j be the index of the topmost element currently present in the stack. While the value arr[i] is less than or equal to the value at the topmost index in the stack and the stack is not empty, keep popping the elements in the stack. Whenever, an element is popped, the left count(CLi) of the current index(i) is updated as CLi = CLi + CLj + 1.
Right count: We calculate the right count for all the indexes similarly. The only difference is we push the elements in the stack while traversing right to left in the array. While arr[i] is strictly less than the value at the topmost index in the stack and the stack is not empty, keep popping the elements. Whenever, an element is popped, the right count of the current index(i) is updated as CRi = CRi + CRj + 1.
Final step: Let ans be the variable containing the final answer. We will initialize it with 0. Then, we will iterate through all the indexes from 1 to n of the array and update the ans as ans = ans + (CLi + 1) * (CRi + 1) * arr[i] for all possible values of i from 1 to n.
Below is the implementation of the above approach:
C++
#include <iostream>
#include <stack>
using namespace std;
int findMinSum( int arr[], int n)
{
int CL[n] = { 0 }, CR[n] = { 0 };
stack< int > q;
for ( int i = 0; i < n; i++) {
while (q.size() != 0 && arr[q.top()] >= arr[i]) {
CL[i] += CL[q.top()] + 1;
q.pop();
}
q.push(i);
}
while (q.size() != 0)
q.pop();
for ( int i = n - 1; i >= 0; i--) {
while (q.size() != 0 && arr[q.top()] > arr[i]) {
CR[i] += CR[q.top()] + 1;
q.pop();
}
q.push(i);
}
while (q.size() != 0)
q.pop();
int ans = 0;
for ( int i = 0; i < n; i++)
ans += (CL[i] + 1) * (CR[i] + 1) * arr[i];
return ans;
}
int main()
{
int arr[] = { 1, 3, 2 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << findMinSum(arr, n);
}
|
Java
import java.util.*;
class GFG
{
static int findMinSum( int arr[], int n)
{
int CL[] = new int [n], CR[] = new int [n];
Stack<Integer> q = new Stack<Integer>();
for ( int i = 0 ; i < n; i++)
{
while (q.size() != 0 && arr[q.peek()] >= arr[i])
{
CL[i] += CL[q.peek()] + 1 ;
q.pop();
}
q.push(i);
}
while (q.size() != 0 )
q.pop();
for ( int i = n - 1 ; i >= 0 ; i--)
{
while (q.size() != 0 && arr[q.peek()] > arr[i])
{
CR[i] += CR[q.peek()] + 1 ;
q.pop();
}
q.push(i);
}
while (q.size() != 0 )
q.pop();
int ans = 0 ;
for ( int i = 0 ; i < n; i++)
ans += (CL[i] + 1 ) * (CR[i] + 1 ) * arr[i];
return ans;
}
public static void main(String[] args)
{
int arr[] = { 1 , 3 , 2 };
int n = arr.length;
System.out.println(findMinSum(arr, n));
}
}
|
Python3
def findMinSum(arr, n):
CL = [ 0 ] * n
CR = [ 0 ] * n
q = []
for i in range ( 0 , n):
while ( len (q) ! = 0 and
arr[q[ - 1 ]] > = arr[i]):
CL[i] + = CL[q[ - 1 ]] + 1
q.pop()
q.append(i)
while len (q) ! = 0 :
q.pop()
for i in range (n - 1 , - 1 , - 1 ):
while ( len (q) ! = 0 and
arr[q[ - 1 ]] > arr[i]):
CR[i] + = CR[q[ - 1 ]] + 1
q.pop()
q.append(i)
while len (q) ! = 0 :
q.pop()
ans = 0
for i in range ( 0 , n):
ans + = (CL[i] + 1 ) * (CR[i] + 1 ) * arr[i]
return ans
if __name__ = = "__main__" :
arr = [ 1 , 3 , 2 ]
n = len (arr)
print (findMinSum(arr, n))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int findMinSum( int []arr, int n)
{
int []CL = new int [n];
int []CR = new int [n];
Stack< int > q = new Stack< int >();
for ( int i = 0; i < n; i++)
{
while (q.Count != 0 && arr[q.Peek()] >= arr[i])
{
CL[i] += CL[q.Peek()] + 1;
q.Pop();
}
q.Push(i);
}
while (q.Count != 0)
q.Pop();
for ( int i = n - 1; i >= 0; i--)
{
while (q.Count != 0 && arr[q.Peek()] > arr[i])
{
CR[i] += CR[q.Peek()] + 1;
q.Pop();
}
q.Push(i);
}
while (q.Count != 0)
q.Pop();
int ans = 0;
for ( int i = 0; i < n; i++)
ans += (CL[i] + 1) * (CR[i] + 1) * arr[i];
return ans;
}
public static void Main(String[] args)
{
int []arr = { 1, 3, 2 };
int n = arr.Length;
Console.WriteLine(findMinSum(arr, n));
}
}
|
Javascript
<script>
function findMinSum(arr, n)
{
var CL = Array(n).fill(0);
var CR = Array(n).fill(0);
var q = [];
for ( var i = 0; i < n; i++) {
while (q.length != 0 && arr[q[q.length-1]] >= arr[i]) {
CL[i] += CL[q[q.length-1]] + 1;
q.pop();
}
q.push(i);
}
while ((q.length) != 0)
q.pop();
for ( var i = n - 1; i >= 0; i--) {
while (q.length != 0 && arr[q[q.length-1]] > arr[i]) {
CR[i] += CR[q[q.length-1]] + 1;
q.pop();
}
q.push(i);
}
while ((q.length) != 0)
q.pop();
var ans = 0;
for ( var i = 0; i < n; i++)
ans += (CL[i] + 1) * (CR[i] + 1) * arr[i];
return ans;
}
var arr = [1, 3, 2 ];
var n = arr.length;
document.write( findMinSum(arr, n));
</script>
|
Complexity Analysis:
- Time complexity: O(n)
- Auxiliary Space: O(n)
Last Updated :
15 Sep, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...