Advertisement

Count of Range Sum - LeetCode 327 Solution

Count of Range Sum - Complete Solution Guide

Count of Range Sum is LeetCode problem 327, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.

Problem Statement

Given an integer array nums and two integers lower and upper , return the number of range sums that lie in [lower, upper] inclusive . Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j inclusive, where i <= j . Example 1: Input: nums = [-2,5,-1], lower = -2, upper = 2 Output: 3 Explanation: The three ranges are: [0,0], [2,2], and [0,2] and their respective sums are: -2, -1, 2. Example 2: Input: nums = [0], lower = 0, upper = 0 Output: 1 Constraints: 1 <= nums

Detailed Explanation

The problem asks us to find the number of subarray sums (range sums) within a given array `nums` that fall between a specified `lower` and `upper` bound (inclusive). A range sum S(i, j) is the sum of elements from index `i` to `j` in `nums`, where `i <= j`. The challenge lies in efficiently counting these valid range sums given the size constraints of the input array.

Solution Approach

The provided solutions employ a Divide and Conquer strategy using a modified Merge Sort algorithm to count the range sums. First, prefix sums are calculated to enable O(1) range sum computation. The core of the solution lies within the merge sort function. During the merge step, we iterate through the right half of the array and, for each element, use two pointers in the left half to find the number of elements within the desired range (val_j - upper, val_j - lower). This process efficiently counts the number of range sums without explicitly calculating them all. Finally, the two halves are merged in sorted order to ensure the correctness of the merge sort algorithm.

Step-by-Step Algorithm

  1. Step 1: Calculate the prefix sums of the input array `nums`. `prefix_sums[i]` stores the sum of elements from `nums[0]` to `nums[i-1]`.
  2. Step 2: Implement a recursive merge sort function `merge_sort_and_count(l, r)` that sorts the `prefix_sums` array within the range `[l, r)` and counts the number of range sums that fall within the `[lower, upper]` bounds.
  3. Step 3: Within the `merge_sort_and_count` function, divide the array into two halves: `[l, mid)` and `[mid, r)`.
  4. Step 4: Recursively call `merge_sort_and_count` on both halves to sort them and count the range sums within each half.
  5. Step 5: During the merge process, iterate through the right half of the array (`[mid, r)`). For each element `prefix_sums[j]` in the right half:
  6. Step 6: Calculate `target_lower = prefix_sums[j] - upper` and `target_upper = prefix_sums[j] - lower`. These represent the range the prefix sum in the left half has to fall within.
  7. Step 7: Use two pointers, `k1` and `k2`, to iterate through the left half of the array (`[l, mid)`) to find the number of elements `prefix_sums[k]` such that `target_lower <= prefix_sums[k] <= target_upper`. `k1` points to the first element >= `target_lower`, and `k2` points to the first element > `target_upper`. The count of valid range sums is `k2 - k1`. This avoids recalculating the range each time by only incrementing the pointers until the next valid value.
  8. Step 8: Merge the two sorted halves (`[l, mid)` and `[mid, r)`) into a single sorted array using a temporary array `temp`.
  9. Step 9: Copy the sorted elements from the `temp` array back into the `prefix_sums` array within the range `[l, r)`.
  10. Step 10: Return the total count of range sums found.
  11. Step 11: Call `merge_sort_and_count(0, n + 1)` to sort the entire `prefix_sums` array and get the final count of range sums.

Key Insights

  • Insight 1: Directly calculating all possible range sums (O(n^2) ranges, O(n) to compute each sum) leads to an O(n^3) solution which is too slow for the given constraints (n <= 10^5).
  • Insight 2: Using prefix sums allows for calculating the sum of any range S(i, j) in O(1) time: S(i, j) = prefix_sum[j+1] - prefix_sum[i].
  • Insight 3: The problem can be efficiently solved using a modified Merge Sort algorithm. During the merge process, we can efficiently count the number of valid range sums by iterating through one half of the sorted prefix sums and using two pointers to identify the indices in the other half that satisfy the range condition.
  • Insight 4: Since integer overflow could occur, the use of long data type is important.

Complexity Analysis

Time Complexity: O(n log n)

Space Complexity: O(n)

Topics

This problem involves: Array, Binary Search, Divide and Conquer, Binary Indexed Tree, Segment Tree, Merge Sort, Ordered Set.

Companies

Asked at: Morgan Stanley.