Open In App

Number of subarrays having sum in a given range

Last Updated : 19 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of integers and a range (L, R). Find the number of subarrays having sum in the range L to R.

Examples: 

Input: arr = { -2, 4, 1, -2}, lower = -4, upper = 1
Output: 5
Explanation: The pairs that are present here are –

  • (1, 1) = [-2] , sum = -2
  • (1, 4) = [-2, 4, 1, -2] , sum = 1
  • (3, 3) = [1] , sum = 1
  • (3, 4) = [1, -2] , sum = -1
  • (4, 4) = [-2] , sum = -2

Input : arr[] = {2, 3, 5, 8}, L = 4, R = 13
Output : 6
Explanation: The subarrays are {2, 3}, {2, 3, 5}, {3, 5}, {5}, {5, 8}, {8}.

Number of subarrays having sum in a given range using Nested loops:

The basic approach to solve this type of question is to try all possible case using brute force method and count all the pair whose sum lie in the range [lower, uppper].

Below is the implementation of the above approach:

C++
#include <iostream>
#include <vector>
using namespace std;

int getCount(vector<int> arr, int n, int lower, int upper) {
    int count = 0;
    for(int i=0; i<n; i++) {
        int sum = 0;
        for(int j=i; j<n; j++) {
            sum += arr[j];
            if(sum >= lower and sum <= upper) {
                count++;
            }
        }
    }
    return count;
}

int main() {
    int n = 4;
    vector<int> arr = {-2, 4, 1, -2};
    int lower = -4, upper = 1;
    int answer = getCount(arr, n, lower, upper);
    cout << answer << endl;
    return 0;
}

Output
5

Time Complexity: O(n^2)
Auxiliary Space: O(1)

Number of subarrays having sum in a given range using Merge Sort:

We will use Merge sort and prefix-sum to solve this problem. we will find the range from the small sorted arrays in the prefix array that lies in the range [lower, upper]. We use prefix array to track the sum and check if the pair lies in the range lower bound and upper bound then lower <= prefix[j] – prefix[i-1] <= upper or lower + prefix[i-1] <= prefix[j] <= upper + prefix[i-1]

Step-by-step approach:

  • Calculate mid of the array by using (start + end)/2
  • Then Recursivly call the function in two seperate half (start, mid) and (mid+1, end).
  • After this Calls the two seperated array (start, mid) and (mid+1, end) are sorted in itself so we can calculate the range of the sum that lies in the prefix array.
  • We will iterate first half (let’s say i) and find the range in the second half(let’s say j) such that prefix[j] should lie in the given range [prefix[i-1 + lower, prefix[i-1]+ upper].
  • Count the number of pairs from the range.
  • When the iteration of i is finished. then we will merge the two half into a single array.

Below is the implementation of the above approach:

C++
#include <iostream>
#include <vector>
using namespace std;

// By Nitin Patel
// Function to merge two sorted subarrays of a given array
void merge(long long start, long long end,
           vector<long long>& prefix)
{
    long long n = end - start + 1;
    long long mid = (start + end) / 2;
    vector<long long> temp(n, 0);
    long long i = start;
    long long j = mid + 1;
    long long k = 0;

    // Merge the two subarrays in sorted order
    while (i <= mid and j <= end) {
        if (prefix[i] <= prefix[j]) {
            temp[k++] = prefix[i++];
        }
        else {
            temp[k++] = prefix[j++];
        }
    }

    // Copy the remaining elements of the left subarray, if
    // any
    while (i <= mid) {
        temp[k++] = prefix[i++];
    }

    // Copy the remaining elements of the right subarray, if
    // any
    while (j <= end) {
        temp[k++] = prefix[j++];
    }

    // Copy the merged subarray back to the original array
    for (int t = start; t <= end; t++) {
        prefix[t] = temp[t - start];
    }
}

// Recursive function to perform merge sort and count
// inversions
long long mergeSort(long long start, long long end,
                    vector<long long>& prefix, int lower,
                    int upper)
{
    if (start == end) {
        long long val = prefix[start];
        // Check if the current element lies within the
        // specified range
        if (val >= (long long)lower
            and val <= (long long)upper) {
            return 1; // Count the element if it's within
                      // the range
        }
        else {
            return 0; // Otherwise, don't count it
        }
    }

    long long mid
        = (start
           + ((end - start)
              >> 1)); // Calculate the middle index
    long long ans = 0; // Initialize the inversion count

    // Recursively count inversions in the left and right
    // halves
    ans += mergeSort(start, mid, prefix, lower, upper);
    ans += mergeSort(mid + 1, end, prefix, lower, upper);

    // Count inversions involving elements from the left and
    // right halves
    long long i = start;
    long long j = mid + 1;
    long long k = mid + 1;
    while (i <= mid) {
        long long lowerbound = lower + prefix[i],
                  upperbound = upper + prefix[i];
        // Find the index in the right half where elements
        // are greater than the upper bound
        while (j <= end and (prefix[j]) <= upperbound) {
            j++;
        }
        // Find the index in the right half where elements
        // are less than the lower bound
        while (k <= end and (prefix[k]) < lowerbound) {
            k++;
        }
        // Count the number of inversions involving elements
        // from the left half and the right half
        ans += (j - k);
        i++;
    }

    // Merge the sorted halves
    merge(start, end, prefix);
    return ans;
}

// Function to count the number of elements within a given
// range in a sorted array
int getCount(vector<int>& nums, int n, int lower, int upper)
{

    vector<long long> prefix(
        n + 1, 0); // Create a prefix sum array
    for (long long i = 1; i <= n; i++) {
        prefix[i] = prefix[i - 1]
                    + nums[i - 1]; // Calculate the prefix
                                   // sum at each index
    }
    return mergeSort(
        1, n, prefix, lower,
        upper); // Perform merge sort and count inversions
}

int main()
{
    int n = 4;
    vector<int> arr = { -2, 4, 1, -2 };
    int lower = -4, upper = 1;
    int answer = getCount(arr, n, lower, upper);
    cout << answer << endl;
    return 0;
}

Output
5

Time Complexity: O(n log n)
Auxiliary Space: O(n)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads