Range Sum of Sorted Subarray Sums

Updated on 11 July, 2025
Range Sum of Sorted Subarray Sums header image

Problem Statement

In this challenge, we are provided with an array nums consisting of n positive integers. We need to compute the sum of all non-empty continuous subarrays within this array, sort these subarray sums in non-decreasing order, and finally return the sum of the elements in this sorted list falling between two given indices, left and right, inclusive.

The sum could potentially be a very large number, thus we should return the result modulo 109 + 7 to avoid overflow and manage large numbers.

Examples

Example 1

Input:

nums = [1,2,3,4], n = 4, left = 1, right = 5

Output:

13

Explanation:

All subarray sums are 1, 3, 6, 10, 2, 5, 9, 3, 7, 4. After sorting them in non-decreasing order we have the new array [1, 2, 3, 3, 4, 5, 6, 7, 9, 10]. The sum of the numbers from index le = 1 to ri = 5 is 1 + 2 + 3 + 3 + 4 = 13.

Example 2

Input:

nums = [1,2,3,4], n = 4, left = 3, right = 4

Output:

6

Explanation:

The given array is the same as example 1. We have the new array [1, 2, 3, 3, 4, 5, 6, 7, 9, 10]. The sum of the numbers from index le = 3 to ri = 4 is 3 + 3 = 6.

Example 3

Input:

nums = [1,2,3,4], n = 4, left = 1, right = 10

Output:

50

Constraints

  • n == nums.length
  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 100
  • 1 <= left <= right <= n * (n + 1) / 2

Approach and Intuition

  1. The core task is to compute the sum of all non-empty continuous subarrays of the given list nums.

  2. After computing these sums, we then sort these values to form a new augmented list.

  3. From this sorted list, the sum of the elements between two specified indices left and right (inclusive) is computed. These indices are based on one-based indexing, which means that left = 1 refers to the first element of the array.

  4. Let's break down the problem with steps given in the example:

    • For nums = [1,2,3,4], all possible subarray sums are calculated. This would include sums like those of [1], [1,2], [1,2,3], ..., [2], [2,3], [2,3,4], etc.
    • All these sums are then sorted.
    • Sum the numbers starting from index left to right in this sorted list.
  5. The computational challenge lies in the efficient calculation of all subarray sums and managing the potentially large number of operations:

    • Iterate over all possible starting points of subarrays within nums.
    • For each starting point, compute the sum for every possible ending point that forms a consecutive subarray.
    • Collect all these sums, sort them, and then calculate the sum of the specified segment of this array.
  6. Given the constraints (1 <= nums.length <= 1000), the brute force calculation of subarray sums results in manageable time complexity, though it is essential to use efficient data structures to keep track of the sums to avoid a slowdown.

By following the steps above, we can systematically derive the sum of the specified elements from the sorted list of subarray sums. Additionally, the modulo operation ensures that the returned results are within a reasonable range, preventing overflow errors.

Solutions

  • C++
cpp
class Solution {
public:
    int sumInRange(vector<int>& array, int size, int low, int high) {
        long totalSum =
            (computeSum(array, size, high) - computeSum(array, size, low - 1)) %
            modulus;
        // Make sure the result is positive
        return (totalSum + modulus) % modulus;
    }
    
private:
    int modulus = 1e9 + 7;
    
    // Calculate subarrays with sum less than or equal to the limit and compute accumulated sum
    pair<int, long long> calculateSums(vector<int>& array, int size, int limit) {
        int numberOfSubarrays = 0;
        long long suffixSum = 0, aggregatedSums = 0, runningSum = 0;
        for (int j = 0, i = 0; j < size; ++j) {
            suffixSum += array[j];
            runningSum += array[j] * (j - i + 1);
            while (suffixSum > limit) {
                runningSum -= suffixSum;
                suffixSum -= array[i++];
            }
            numberOfSubarrays += j - i + 1;
            aggregatedSums += runningSum;
        }
        return {numberOfSubarrays, aggregatedSums};
    }
    
    // Compute sum of first k smallest sums in subarrays
    long long computeSum(vector<int>& array, int size, int k) {
        int lowestSum = *min_element(array.begin(), array.end());
        int highestSum = accumulate(array.begin(), array.end(), 0);
        int l = lowestSum, r = highestSum;
    
        while (l <= r) {
            int mid = l + (r - l) / 2;
            if (calculateSums(array, size, mid).first >= k)
                r = mid - 1;
            else
                l = mid + 1;
        }
        auto [subarrayCount, sumResult] = calculateSums(array, size, l);
        // Adjust sum for exact k subarrays
        return sumResult - l * (subarrayCount - k);
    }
};

The given C++ class defined as Solution focuses on computing the range sum of sorted subarray sums for a given numerical array. Here's a breakdown of how the methods within the class work to achieve this:

  • sumInRange Function: This public member function takes an array, its size, and a range specified by lower (low) and upper (high) limits to compute the sum of all subarray sums that fall within the specified range. The method utilizes the computeSum function to calculate the sums and then adjusts the calculated sums to ensure the result is non-negative by applying modulus arithmetic.

  • computeSum Function: This private member function computes the sum of the smallest k-sized subarray sums. It uses binary search (narrowing down the range between the smallest sum and the cumulative sum of the array) to efficiently find the right set of subarray sums that fit within the size k constraint.

  • calculateSums Function: Another private member function essential for the execution of computeSum. This function calculates the number of possible subarrays and the cumulative sum of their elements that do not exceed a given limit. It implements a sliding window approach to maintain the running sum and count of subarrays conformatively with the increasing and decreasing bounds.

Given this structure, the solution is efficient in handling large inputs with the following properties:

  • Modular arithmetic ensures the results are within bounds,
  • Binary search leverages efficiency in finding the correct subarray sum constraints,
  • Sliding window technique optimizes calculation of running subarray sums.

Complete the following implementations when using this class:

  • Make sure the array input is appropriately preprocessed if necessary before invoking the sumInRange method.
  • It's crucial to understand how the range values (low - high) influence the results to predict the function output correctly.
  • Java
java
import java.util.*;
    
public class Solution {
    
    private static final int MODULUS = 1000000007;
    
    public int calculateRangeSum(int[] elements, int length, int start, int end) {
        long sum =
            (sumSubarray(elements, length, end) - sumSubarray(elements, length, start - 1)) %
            MODULUS;
        // Result will always be positive
        return (int) ((sum + MODULUS) % MODULUS);
    }
    
    // Calculate both count of subarrays and their cumulative sum up to a given target.
    private Map.Entry<Integer, Long> computeCountAndSum(
        int[] elements,
        int length,
        int cap
    ) {
        int total = 0;
        long currentTotal = 0, sumAccumulated = 0, aggregateSum = 0;
        for (int j = 0, i = 0; j < length; ++j) {
            currentTotal += elements[j];
            aggregateSum += elements[j] * (j - i + 1);
            while (currentTotal > cap) {
                aggregateSum -= currentTotal;
                currentTotal -= elements[i++];
            }
            total += j - i + 1;
            sumAccumulated += aggregateSum;
        }
        return new AbstractMap.SimpleEntry<>(total, sumAccumulated);
    }
    
    // Function to compute the sum of the smallest k subarray sums.
    private long sumSubarray(int[] elements, int length, int k) {
        int minimum = Arrays.stream(elements).min().getAsInt();
        int maximum = Arrays.stream(elements).sum();
        int left = minimum, right = maximum;
    
        while (left <= right) {
            int midpoint = left + (right - left) / 2;
            if (computeCountAndSum(elements, length, midpoint).getKey() >= k) right = midpoint - 1;
            else left = midpoint + 1;
        }
        Map.Entry<Integer, Long> result = computeCountAndSum(elements, length, left);
        // Adjust sum based on subarrays count beyond k using the same sum left.
        return result.getValue() - left * (result.getKey() - k);
    }
}

To solve the problem of calculating the range sum of sorted subarray sums in Java, the code employs several sophisticated algorithms combined with efficient data handling techniques. Here are the detailed steps and methodologies used in the code:

  • Modulo Operation for Results: Utilize the constant MODULUS to compute the sum result modulo 1000000007 to ensure manageable numbers and avoid overflow.

  • Calculate Range Sum with Boundary Conditions: Compute the range sum by first computing the sum up to the end limit and subtracting the sum up to start-1. This ensures that only the sums of subarrays falling within the defined range are considered.

  • Efficient Sum and Count Computation: Implement a helper method computeCountAndSum() that calculates both the total number of valid subarrays and their cumulative sums that do not exceed a specified cap. This employs the two-pointer technique for efficient checking of subarray sums against the cap, updating counts and current sum in a streaming manner.

  • Binary Search for Threshold Adjustment: Use binary search to find the precise subarray sum threshold which helps in determining the kth smallest subarray sums efficiently. Adjustments are made based on the midpoint calculations within the binary search loop to home in on the correct threshold swiftly.

  • Calculate Sum of Smallest k Subarrays: After determining the correct threshold for the sum of smallest k subarray sums through binary search, the code further adjusts the calculated sum based on the difference in the actual count from k. This is done by subtracting the excess sums that have been included due to the threshold algorithm.

By following the above methodology, this implementation ensures an optimal and accurate solution for finding the range sum of sorted subarray sums. Each function plays a pivotal role in breaking down the problem into manageable parts, enabling efficient and effective problem-solving. The use of modulo ensures that even very large numbers are handled gracefully, and the binary search and two-pointer technique make the implementation both time and memory efficient.

  • Python
python
class Solution:
    def sumOfRanges(self, sequence, length, start, end):
        modulo = 10**9 + 7
    
        def calc_sum_and_count(sequence, length, limit):
            count = 0
            prefix_sum = 0
            accumulated_sum = 0
            subarray_sum = 0
            start_index = 0
            for end_index in range(length):
                prefix_sum += sequence[end_index]
                subarray_sum += sequence[end_index] * (end_index - start_index + 1)
                while prefix_sum > limit:
                    subarray_sum -= prefix_sum
                    prefix_sum -= sequence[start_index]
                    start_index += 1
                count += end_index - start_index + 1
                accumulated_sum += subarray_sum
            return count, accumulated_sum
    
        def kth_sum(sequence, length, k):
            lowest_sum = min(sequence)
            highest_sum = sum(sequence)
            min_bound = lowest_sum
            max_bound = highest_sum
    
            while min_bound <= max_bound:
                middle = min_bound + (max_bound - min_bound) // 2
                if calc_sum_and_count(sequence, length, middle)[0] >= k:
                    max_bound = middle - 1
                else:
                    min_bound = middle + 1
            count, total = calc_sum_and_count(sequence, length, min_bound)
            # Adjust the total for exact k sums
            return total - min_bound * (count - k)
    
        final_result = (
            kth_sum(sequence, length, end) - kth_sum(sequence, length, start - 1)
        ) % modulo
        # Adjustment for modulo operation result
        return (final_result + modulo) % modulo

In this Python solution, the problem solves the "Range Sum of Sorted Subarray Sums". The code accomplishes the computation using a two-step process combining binary search mechanisms with a prefix sum strategy to efficiently calculate subarray sums.

  • Subarray Sum Calculation: This part involves computing the sum of all subarray sums not exceeding a specified limit. An inner loop iterates through the array, cumulatively adding array elements to prefix_sum and their weighted value to subarray_sum. If prefix_sum exceeds the limit, adjustments are made by reducing contributions from the beginning of the current subarray, ensuring the sum meets the constraint. This results in the dynamic adjustment of the subarray start index and computation of associated counts of valid subarrays and their accumulated sums.

  • k-th Sum Determination: Here, binary search is employed to pinpoint the smallest sum, min_bound, such that there are at least k subarrays whose sums are less than or equal to min_bound. This aids in finding precise k-th subarray sum totals required for the final summation range.

The final summation is determined by calculating the difference between the sum at the end index and the sum before the start index, adjusted modulo (10^9 + 7), primarily to handle large numbers and prevent overflow. This approach ensures that the complex problem of summing sorted subarray sums within a bounded range is resolved efficiently and accurately within logarithmic time complexity bounds, leveraging subarray prefix sum techniques and binary search.

Comments

No comments yet.