Sum of Max of Subarrays (original) (raw)

Last Updated : 21 Feb, 2025

Given an array **arr[], the task is to find the sum of the maximum **elements of every possible non-empty sub-arrays of the given array **arr[].

**Examples:

**Input: arr[] = [1, 3, 2]
**Output: 15
**Explanation: All possible non-empty subarrays of [1, 3, 2] are {1}, {3}, {2}, {1, 3}, {3, 2} and {1, 3, 2}. The maximum elements of the subarrays are 1, 3, 2, 3, 3, 3 respectively. The sum will be 15.

**Input: arr[] = [3, 1]
**Output: 7
**Explanation: All possible non-empty subarrays of [3, 1] are {3}, {1} and {3, 1}. The maximum elements of the subarrays are 3, 1, 3 respectively. The sum will be 7.

**Input: arr[] = [8, 0, 1]
**Output: 26
**Explanation: All possible non-empty subarrays of [8, 0, 1] are {8}, {0}, {1}, {8, 0}, {0, 1} and {8, 0, 1}. The maximum elements of the subarrays are 8, 0, 1, 8, 1, 8 respectively. The sum will be 26.

Try It Yourselfredirect icon

Table of Content

[Naive Approach] Generate all Subarrays - O(**) Time and O(1) Space

The **idea is to compute the **sum of the **maximum elements of **all possible subarrays of the given array. To do this, we **generate all subarrays, find their **maximum element, and **sum up these **maximum values.

Below is the implementation of the above approach:

C++ `

// C++ implementation to find sum of max // of subarrays by generating all subarrays #include <bits/stdc++.h> using namespace std;

int sumOfMax(vector& arr) { int n = arr.size(); int res = 0;

// Pick starting point of subarray
for (int i = 0; i < n; ++i) {
    int currMax = arr[i];
    
    // Pick ending point
    for (int j = i; j < n; ++j) {
      
        // Max of subarray from i to j
        currMax = max(currMax, arr[j]);  
        res += currMax;          
    }
}

return res;

}

int main() { vector arr = {1, 3, 2}; cout << sumOfMax(arr) << endl; return 0; }

C

// C implementation to find sum of max // of subarrays by generating all subarrays #include <stdio.h>

int sumOfMax(int arr[], int n) { int res = 0;

// Pick starting point of subarray
for (int i = 0; i < n; ++i) {
    int currMax = arr[i];

    // Pick ending point
    for (int j = i; j < n; ++j) {

        // Max of subarray from i to j
        if (arr[j] > currMax) {
            currMax = arr[j];
        }
        
        res += currMax;
    }
}

return res;

}

int main() { int arr[] = {1, 3, 2}; int n = sizeof(arr) / sizeof(arr[0]);

printf("%d\n", sumOfMax(arr, n));

return 0;

}

Java

// Java implementation to find sum of max // of subarrays by generating all subarrays import java.util.*;

class GfG {

static int sumOfMax(int[] arr) {
    int n = arr.length;
    int res = 0;

    // Pick starting point of subarray
    for (int i = 0; i < n; ++i) {
        int currMax = arr[i];

        // Pick ending point
        for (int j = i; j < n; ++j) {

            // Max of subarray from i to j
            currMax = Math.max(currMax, arr[j]);
            res += currMax;
        }
    }

    return res;
}

public static void main(String[] args) {
    int[] arr = {1, 3, 2};
    System.out.println(sumOfMax(arr));
}

}

Python

Python implementation to find sum of max

of subarrays by generating all subarrays

def sumOfMax(arr): n = len(arr) res = 0

# Pick starting point of subarray
for i in range(n):
    currMax = arr[i]

    # Pick ending point
    for j in range(i, n):

        # Max of subarray from i to j
        currMax = max(currMax, arr[j])
        
        res += currMax

return res

if name == "main": arr = [1, 3, 2] print(sumOfMax(arr))

C#

// C# implementation to find sum of max // of subarrays by generating all subarrays using System;

class GfG {

static int sumOfMax(int[] arr) {
    int n = arr.Length;
    int res = 0;

    // Pick starting point of subarray
    for (int i = 0; i < n; ++i) {
        int currMax = arr[i];

        // Pick ending point
        for (int j = i; j < n; ++j) {

            // Max of subarray from i to j
            currMax = Math.Max(currMax, arr[j]);
            res += currMax;
        }
    }

    return res;
}

static void Main() {
    int[] arr = {1, 3, 2};
    Console.WriteLine(sumOfMax(arr));
}

}

JavaScript

// Javascript implementation to find sum of max // of subarrays by generating all subarrays function sumOfMax(arr) { let n = arr.length; let res = 0;

// Pick starting point of subarray
for (let i = 0; i < n; i++) {
    let currMax = arr[i];
    
    // Pick ending point
    for (let j = i; j < n; j++) {
    
        // Max of subarray from i to j
        currMax = Math.max(currMax, arr[j]);  
        res += currMax;
    }
}
return res;

}

// Driver Code let arr = [1, 3, 2]; console.log(sumOfMax(arr));

`

**Time Complexity: O(n²) due to the nested loops iterating over all subarrays.
**Space Complexity: O(1) as no extra space is used apart from variables.

[Expected Approach] Using Monotonic Stack - O(n) Time and O(n) Space

The idea is to efficiently compute the sum of the maximum elements of all subarrays using a **monotonic stack approach instead of brute force. Instead of generating all subarrays explicitly, we determine how many subarrays each element contributes as the **maximum value.

To achieve this, we find for each element the number of subarrays where it remains the maximum by computing its **left boundary (how many contiguous elements to the left it dominates) and **right boundary (how many contiguous elements to the right it dominates). This is done using a **monotonic stack, which efficiently finds the nearest greater elements to the left and right in **O(n) time.

The contribution of each element to the total sum is then given by multiplying its value with the number of subarrays in which it is the maximum ****(** left[i] * right[i] ), ensuring an optimal and direct computation of the result without generating all subarrays explicitly.

Steps to implement the above idea:

Below is the implementation of the above approach:

C++ `

// C++ implementation to find sum of max // of subarrays using Monotonic Stack #include <bits/stdc++.h> using namespace std;

int sumOfMax(vector& arr) {

int n = arr.size();
int res = 0;
stack<int> stk;
vector<int> left(n), right(n);

// Finding the left boundary for each element
for (int i = 0; i < n; ++i) {
    
    // Pop elements smaller than arr[i] from stack
    while (!stk.empty() && arr[stk.top()] < arr[i]) {
        stk.pop();
    }
    
    // Calculate left boundary count
    left[i] = (stk.empty()) ? (i + 1) : (i - stk.top());
    
    // Push current index into stack
    stk.push(i);
}

// Clear the stack for right boundary computation
while (!stk.empty()) {
    stk.pop();
}

// Finding the right boundary for each element
for (int i = n - 1; i >= 0; --i) {
    
    // Pop elements smaller or equal to arr[i] from stack
    while (!stk.empty() && arr[stk.top()] <= arr[i]) {
        stk.pop();
    }
    
    // Calculate right boundary count
    right[i] = (stk.empty()) ? (n - i) : (stk.top() - i);
    
    // Push current index into stack
    stk.push(i);
}

// Compute sum of max elements of all subarrays
for (int i = 0; i < n; ++i) {
    
    // Contribution of arr[i] as max in subarrays
    res += arr[i] * left[i] * right[i];
}

return res;

}

int main() { vector arr = {1, 3, 2};

// Print the sum of maximum elements in all subarrays
cout << sumOfMax(arr) << endl;
return 0;

}

Java

// Java implementation to find sum of max // of subarrays using Monotonic Stack import java.util.*;

class GfG { static int sumOfMax(int[] arr) { int n = arr.length; int res = 0; Stack stk = new Stack<>(); int[] left = new int[n], right = new int[n];

    // Finding the left boundary for each element
    for (int i = 0; i < n; ++i) {
        
        // Pop elements smaller than arr[i] from stack
        while (!stk.isEmpty() && arr[stk.peek()] < arr[i]) {
            stk.pop();
        }

        // Calculate left boundary count
        left[i] = (stk.isEmpty()) ? (i + 1) : (i - stk.peek());

        // Push current index into stack
        stk.push(i);
    }

    // Clear the stack for right boundary computation
    stk.clear();

    // Finding the right boundary for each element
    for (int i = n - 1; i >= 0; --i) {
        
        // Pop elements smaller or equal to arr[i] from stack
        while (!stk.isEmpty() && arr[stk.peek()] <= arr[i]) {
            stk.pop();
        }

        // Calculate right boundary count
        right[i] = (stk.isEmpty()) ? (n - i) : (stk.peek() - i);

        // Push current index into stack
        stk.push(i);
    }

    // Compute sum of max elements of all subarrays
    for (int i = 0; i < n; ++i) {

        // Contribution of arr[i] as max in subarrays
        res += arr[i] * left[i] * right[i];
    }

    return res;
}

public static void main(String[] args) {
    int[] arr = {1, 3, 2};
    System.out.println(sumOfMax(arr));
}

}

Python

Python implementation to find sum of max

of subarrays using Monotonic Stack

def sumOfMax(arr): n = len(arr) res = 0 stk = [] left = [0] * n right = [0] * n

# Finding the left boundary for each element
for i in range(n):

    # Pop elements smaller than arr[i] from stack
    while stk and arr[stk[-1]] < arr[i]:
        stk.pop()

    # Calculate left boundary count
    left[i] = (i + 1) if not stk else (i - stk[-1])

    # Push current index into stack
    stk.append(i)

# Clear the stack for right boundary computation
stk.clear()

# Finding the right boundary for each element
for i in range(n - 1, -1, -1):

    # Pop elements smaller or equal to arr[i] from stack
    while stk and arr[stk[-1]] <= arr[i]:
        stk.pop()

    # Calculate right boundary count
    right[i] = (n - i) if not stk else (stk[-1] - i)

    # Push current index into stack
    stk.append(i)

# Compute sum of max elements of all subarrays
for i in range(n):

    # Contribution of arr[i] as max in subarrays
    res += arr[i] * left[i] * right[i]

return res

if name == "main": arr = [1, 3, 2]

# Print the sum of maximum elements in all subarrays
print(sumOfMax(arr))

C#

// C# implementation to find sum of max // of subarrays using Monotonic Stack using System; using System.Collections.Generic;

class GfG { static int sumOfMax(int[] arr) { int n = arr.Length; int res = 0; Stack stk = new Stack(); int[] left = new int[n], right = new int[n];

    // Finding the left boundary for each element
    for (int i = 0; i < n; ++i) {
        
        // Pop elements smaller than arr[i] from stack
        while (stk.Count > 0 && arr[stk.Peek()] < arr[i]) {
            stk.Pop();
        }

        // Calculate left boundary count
        left[i] = (stk.Count == 0) ? (i + 1) : (i - stk.Peek());

        // Push current index into stack
        stk.Push(i);
    }

    // Clear the stack for right boundary computation
    stk.Clear();

    // Finding the right boundary for each element
    for (int i = n - 1; i >= 0; --i) {
        
        // Pop elements smaller or equal to arr[i] from stack
        while (stk.Count > 0 && arr[stk.Peek()] <= arr[i]) {
            stk.Pop();
        }

        // Calculate right boundary count
        right[i] = (stk.Count == 0) ? (n - i) : (stk.Peek() - i);

        // Push current index into stack
        stk.Push(i);
    }

    // Compute sum of max elements of all subarrays
    for (int i = 0; i < n; ++i) {

        // Contribution of arr[i] as max in subarrays
        res += arr[i] * left[i] * right[i];
    }

    return res;
}

static void Main() {
    int[] arr = {1, 3, 2};
    Console.WriteLine(sumOfMax(arr));
}

}

JavaScript

// JavaScript implementation to find sum of max // of subarrays using Monotonic Stack

function sumOfMax(arr) { let n = arr.length; let res = 0; let stk = []; let left = new Array(n).fill(0); let right = new Array(n).fill(0);

// Finding the left boundary for each element
for (let i = 0; i < n; ++i) {

    // Pop elements smaller than arr[i] from stack
    while (stk.length > 0 && arr[stk[stk.length - 1]] < arr[i]) {
        stk.pop();
    }

    // Calculate left boundary count
    left[i] = (stk.length === 0) ? (i + 1) : (i - stk[stk.length - 1]);

    // Push current index into stack
    stk.push(i);
}

// Clear the stack for right boundary computation
stk = [];

// Finding the right boundary for each element
for (let i = n - 1; i >= 0; --i) {

    // Pop elements smaller or equal to arr[i] from stack
    while (stk.length > 0 && arr[stk[stk.length - 1]] <= arr[i]) {
        stk.pop();
    }

    // Calculate right boundary count
    right[i] = (stk.length === 0) ? (n - i) : (stk[stk.length - 1] - i);

    // Push current index into stack
    stk.push(i);
}

// Compute sum of max elements of all subarrays
for (let i = 0; i < n; ++i) {

    // Contribution of arr[i] as max in subarrays
    res += arr[i] * left[i] * right[i];
}

return res;

}

// Driver Code let arr = [1, 3, 2]; console.log(sumOfMax(arr));

`

**Time Complexity: O(n) since each element is processed at most twice using monotonic stacks.
**Space Complexity: O(n)due to the left, right, and stk arrays.