Skip to content

2104. Sum of Subarray Ranges

Description

You are given an integer array nums. The range of a subarray of nums is the difference between the largest and smallest element in the subarray.

Return the sum of all subarray ranges of nums.

A subarray is a contiguous non-empty sequence of elements within an array.

 

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

 

Follow-up: Could you find a solution with O(n) time complexity?

 

Solutions

Solution: Monotonic Stack

  • Time complexity: O(n)
  • Space complexity: O(n)

 

JavaScript

js
/**
 * @param {number[]} nums
 * @return {number}
 */
const subArrayRanges = function (nums) {
  const compareSmall = (num, target) => num < target;
  const compareLarge = (num, target) => num > target;
  const sumRanges = (edge, compare) => {
    const stack = [];
    let result = 0;

    for (let index = 0; index <= nums.length; index++) {
      const num = nums[index] ?? edge;

      while (stack.length && compare(num, nums[stack.at(-1)])) {
        const previous = stack.pop();
        const start = stack.length ? stack.at(-1) : -1;
        const count = (index - previous) * (previous - start);

        result += nums[previous] * count;
      }
      stack.push(index);
    }
    return result;
  };
  const sumLargest = sumRanges(Number.MAX_SAFE_INTEGER, compareLarge);
  const sumSmallest = sumRanges(Number.MIN_SAFE_INTEGER, compareSmall);

  return sumLargest - sumSmallest;
};

Released under the MIT license