Sum of Subarray Ranges

Updated on 14 July, 2025
Sum of Subarray Ranges header image

Problem Statement

In this problem, you are provided with an integer array named nums. You need to calculate the range of each possible subarray within nums and then return the sum of all these ranges. The range of a subarray is defined as the difference between the largest and smallest elements in that subarray. It is important to note that a subarray is a contiguous sequence of elements from the array, and every subarray should have at least one element. This problem requires not just generating each subarray, but computing the range for each and accumulating these ranges.

Examples

Example 1

Input:

nums = [1,2,3]

Output:

4

Explanation:

The 6 subarrays of nums are the following:
[1], range = largest - smallest = 1 - 1 = 0
[2], range = 2 - 2 = 0
[3], range = 3 - 3 = 0
[1,2], range = 2 - 1 = 1
[2,3], range = 3 - 2 = 1
[1,2,3], range = 3 - 1 = 2
So the sum of all ranges is 0 + 0 + 0 + 1 + 1 + 2 = 4.

Example 2

Input:

nums = [1,3,3]

Output:

4

Explanation:

The 6 subarrays of nums are the following:
[1], range = largest - smallest = 1 - 1 = 0
[3], range = 3 - 3 = 0
[3], range = 3 - 3 = 0
[1,3], range = 3 - 1 = 2
[3,3], range = 3 - 3 = 0
[1,3,3], range = 3 - 1 = 2
So the sum of all ranges is 0 + 0 + 0 + 2 + 0 + 2 = 4.

Example 3

Input:

nums = [4,-2,-3,4,1]

Output:

59

Explanation:

The sum of all subarray ranges of nums is 59.

Constraints

  • 1 <= nums.length <= 1000
  • -109 <= nums[i] <= 109

Approach and Intuition

When attempting a solution to determine the sum of ranges of all subarrays in an array, understanding the following can be critical to optimizing and correctly solving the problem:

  1. Generation of Subarrays: All contiguous subarrays must be considered. For an array of length n, there are n*(n+1)/2 possible subarrays.

  2. Calculation of Range: For each subarray, the range is calculated as the difference between the maximum and minimum values within the subarray.

By observing the problem through examples:

  • For nums = [1,2,3]:

    • Subarrays are [1], [2], [3], [1,2], [2,3], and [1,2,3].
    • The range of these subarrays are 0, 0, 0, 1, 1, and 2 respectively, summing to 4.
  • For nums = [1,3,3]:

    • Subarrays are [1], [3], [3], [1,3], [3,3], and [1,3,3].
    • The range of these subarrays are 0, 0, 0, 2, 0, and 2 respectively, giving a sum again of 4.
  • For nums = [4,-2,-3,4,1]:

    • The sum of all subarrays' ranges is calculated as 59.

Strategies for Implementation:

  • A naive approach would involve using a nested loop: the outer loop to start the subarray and the inner loop to end the subarray. This allows calculation of the min and max for each subarray directly but results in a time complexity of O(n^3) in the worst case, which may not be efficient for larger arrays.

  • An optimized approach can utilize precomputation techniques or data structures like segment trees to efficiently query min and max values over any subarray, thus reducing the time complexity.

Considering the constraints:

  • With array lengths up to 1000 and element values ranging from -10^9 to 10^9, a solution needs to efficiently manage potentially large inputs and minimize the number of operations involved in range calculations.

Thus, you'd weigh the naive method against more complex but potentially more efficient methods depending on the size constraints given by the problem.

Solutions

  • C++
cpp
class Solution {
public:
    long long rangeDifference(vector<int>& elements) {
        int length = elements.size();
        long long result = 0;
        stack<int> stackHelper;
    
        // Summing all minimum elements ranges
        for (int i = 0; i <= length; ++i) {
            while (!stackHelper.empty() &&
                   (i == length || elements[stackHelper.top()] >= elements[i])) {
                int position = stackHelper.top();
                stackHelper.pop();
                int leftIndex = stackHelper.empty() ? -1 : stackHelper.top();
                result -= (long long)elements[position] * (i - position) * (position - leftIndex);
            }
            stackHelper.push(i);
        }
    
        // Summing all maximum elements ranges
        stackHelper.pop();
        for (int i = 0; i <= length; ++i) {
            while (!stackHelper.empty() &&
                   (i == length || elements[stackHelper.top()] <= elements[i])) {
                int position = stackHelper.top();
                stackHelper.pop();
                int leftIndex = stackHelper.empty() ? -1 : stackHelper.top();
                result += (long long)elements[position] * (i - position) * (position - leftIndex);
            }
            stackHelper.push(i);
        }
        return result;
    }
};

The solution provided involves computing the sum of subarray ranges using a monotonic stack method in C++. The function, named rangeDifference, calculates the difference between the sum of maximum and minimum elements' contributions across all subarrays of a given input vector elements.

Follow these steps to understand the implementation of this solution:

  1. Initialize necessary variables:

    • A long long type variable named result to store the calculated range difference.
    • An integer length to hold the size of the input vector.
    • A stack of integers stackHelper to assist with the identification of minimum and maximum elements in subarrays.
  2. Calculate contributions of minimum range values in all subarrays:

    • Iterate through each element in the vector with an extra loop iteration to handle edge cases.
    • Use the stack to keep track of indices with increasing values and simultaneously calculate the minimum range sum.
    • For each element, determine the appropriate subarray boundaries and use these to decrease the result.
  3. Clear the stack after processing minimum elements to reuse it for maximum elements.

  4. Calculate contributions of maximum range values in all subarrays:

    • Similar to the above, but track indices with decreasing values to appropriately calculate the maximum range sum.
    • For each element, determine subarray boundaries and update the result by adding to it.
  5. Finally, return the value of result, which now contains the range difference between the sum of all maximum and minimum subarray elements.

This approach efficiently computes the result by leveraging stack operations to keep track of subarray boundaries, avoiding the need for nested loops typically used in brute-force solutions. The complexity remains linear relative to the number of elements in the input vector due to the stack-based implementation.

  • Java
java
class Solution {
    
    public long rangeDifference(int[] elements) {
        int length = elements.length;
        long result = 0;
        Stack<Integer> stack = new Stack<>();
    
        // Handle minimum values sum
        for (int end = 0; end <= length; ++end) {
            while (
                !stack.isEmpty() &&
                (end == length || elements[stack.peek()] >= elements[end])
            ) {
                int center = stack.peek();
                stack.pop();
                int start = stack.isEmpty() ? -1 : stack.peek();
                result -= (long) elements[center] * (end - center) * (center - start);
            }
            stack.push(end);
        }
    
        // Handle maximum values sum
        stack.clear();
        for (int end = 0; end <= length; ++end) {
            while (
                !stack.isEmpty() &&
                (end == length || elements[stack.peek()] <= elements[end])
            ) {
                int center = stack.peek();
                stack.pop();
                int start = stack.isEmpty() ? -1 : stack.peek();
                result += (long) elements[center] * (end - center) * (center - start);
            }
            stack.push(end);
        }
        return result;
    }
}

This Java solution tackles the problem of calculating the sum of subarray ranges using a rangeDifference method. The method computes the difference between the sums of maximum values and minimum values of all subarrays within the provided array of integers.

Here's how the code operates:

  1. The method rangeDifference accepts an array elements and initializes variables including length for the array length, and result initially set to zero for storing the final difference in sums.
  2. A Stack<Integer> is used to manage indices during the computation.

The process is divided into two main phases:

  1. Handling minimum values sum:

    • Iterate through the array using a variable end from 0 to length.
    • For each element, if the current stack is not empty and the element at the index of the stack's top is greater than or equal to the current element (or if end equals length), compute the contribution of the subarray with respect to the minimum value and subtract it from result.
    • Push the current index end onto the stack after processing.
  2. Handling maximum values sum:

    • Clear the stack for a fresh start.
    • Iterate through the array in a similar manner to the minimum values computation.
    • This time, add the contribution of the subarray with respect to the maximum value to result.

Finally, the method returns result, which now holds the total difference between the sum of maximum values and the sum of minimum values across all subarrays.

This approach efficiently computes the desired range difference utilizing stack data structure to maintain the indices, optimizing the process of subarray range calculation.

  • Python
python
class Solution:
    def sumOfSubarrayRanges(self, values: List[int]) -> int:
        length, total = len(values), 0 
        temp_stack = []
            
        # Calculate sum of minimums in all subarrays
        for end_idx in range(length + 1):
            while temp_stack and (end_idx == length or values[temp_stack[-1]] > values[end_idx]):
                middle = temp_stack.pop()
                start = -1 if not temp_stack else temp_stack[-1]
                total -= values[middle] * (middle - start) * (end_idx - middle)
            temp_stack.append(end_idx)
    
        # Calculate sum of maximums in all subarrays
        temp_stack.clear()
        for end_idx in range(length + 1):
            while temp_stack and (end_idx == length or values[temp_stack[-1]] < values[end_idx]):
                middle = temp_stack.pop()
                start = -1 if not temp_stack else temp_stack[-1]
                total += values[middle] * (middle - start) * (end_idx - middle)
            temp_stack.append(end_idx)
            
        return total

Below is a summary of how the given Python code calculates the sum of ranges in subarrays:

  • First, define a function within a Solution class called sumOfSubarrayRanges which accepts a list of integers (values).

  • Initialize variables for the length of the list (length), the resultant total sum (total), and a temporary stack (temp_stack) to facilitate range calculations.

  • Solve for the sum total of minimum values across all the subarrays:

    • Iterate over the range 0 to length + 1.
    • In each iteration, pop elements from temp_stack if it's non-empty and the next value is less than or they're at the last index. Calculate the subarray's range minimum contribution to the total and subtract it.
    • Append the current index to temp_stack whether or not elements were popped.
  • Reset temp_stack for second iteration.

  • Repeat a similar procedure to calculate the sum of the maximum values in the subarrays:

    • Iterate similarly from 0 to length + 1.
    • Conditions for popping from the stack change to check for larger values, and the contributions are added to the total instead of subtracted.
  • The final value of total represents the sum of the ranges of all possible subarrays from the values list, obtained by subtracting all subarray minimum values and adding all subarray maximum values. The function ultimately returns this total.

Comments

No comments yet.