Count Subarrays With Fixed Bounds

Solution For Count Subarrays With Fixed Bounds

Problem Statement:

Given an array of integers nums and two integers lower and upper, find the number of contiguous subarrays whose sum lies within the range [lower, upper].

Example:

Input: nums = [-2,5,-1], lower = -2, upper = 2
Output: 3
Explanation: The three subarrays are [-2], [5,-1] and [-2,5,-1] and their respective sums are -2, 4, 2.

Solution:

The given problem can be solved using Divide and Conquer approach. We start by dividing the given array into two parts, left and right.

We recursively find all the subarrays whose sum lies within [lower, upper] range in the left and right parts. To find subarrays in the left part, we need to consider all the subarrays that end at an element in the left part. Similarly, to find subarrays in the right part, we need to consider all the subarrays that start at an element in the right part.

Now, let’s focus on finding all the subarrays that end at an element in the left part. To do this, we traverse through the left part of the array and maintain a prefix sum. At each element, we check if the prefix sum lies within the [lower, upper] range. To find all subarrays that end at this element, we check how many prefix sums lie within the range [prefix_sum – upper, prefix_sum – lower]. We can use a binary search to find the number of prefix sums in this range.

Similarly, to find all subarrays that start at an element in the right part, we traverse through the right part of the array and maintain a suffix sum. At each element, we check if the suffix sum lies within the [lower, upper] range. To find all subarrays that start at this element, we check how many suffix sums lie within the range [suffix_sum – upper, suffix_sum – lower]. We can use a binary search to find the number of suffix sums in this range.

Finally, we add up the count of subarrays found in the left and right parts of the array to get the total count of subarrays whose sum lies within the given range.

Let’s look at the implementation of the above approach:

public class Solution {
public int countRangeSum(int[] nums, int lower, int upper) {
int n = nums.length;
long[] prefixSum = new long[n + 1];
for (int i = 0; i < n; i++) {
prefixSum[i + 1] = prefixSum[i] + nums[i];
}
return countSubarrays(prefixSum, 0, n, lower, upper);
}

private int countSubarrays(long[] prefixSum, int left, int right, int lower, int upper) {
    if (right - left <= 1) {
        return 0;
    }

    int mid = left + (right - left) / 2;
    int count = countSubarrays(prefixSum, left, mid, lower, upper) 
              + countSubarrays(prefixSum, mid, right, lower, upper);

    int i = left, j = mid, k = mid;
    long[] merged = new long[right - left];
    int t = 0;
    while (i < mid) {
        while (j < right && prefixSum[j] - prefixSum[i] < lower) {
            j++;
        }
        while (k < right && prefixSum[k] - prefixSum[i] <= upper) {
            k++;
        }
        count += k - j;

        while (t < right - left && prefixSum[i] > prefixSum[j]) {
            merged[t++] = prefixSum[j++] - prefixSum[left];
        }
        merged[t++] = prefixSum[i++] - prefixSum[left];
    }

    System.arraycopy(merged, 0, prefixSum, left, t);
    return count;
}

}

The above solution has a time complexity of O(nlogn) and space complexity of O(n).

Step by Step Implementation For Count Subarrays With Fixed Bounds

Given an array A of integers and two integers L and R, find the number of subarrays A[i], A[i+1], ..., A[j] with i <= j and L <= A[i] <= A[i+1] <= ... <= A[j] <= R.

class Solution {
    public int numSubarrayBoundedMax(int[] A, int L, int R) {
        int j = 0, count = 0, res = 0;
        for (int i = 0; i < A.length; i++) {
            if (A[i] > R) {
                count = 0;
                j = i + 1;
            } else if (A[i] >= L) {
                count = i - j + 1;
                res += count;
            } else {
                res += count;
            }
        }
        return res;
    }
}
def countSubarrays(arr, n, k): 

# Initialize result 
res = 0

# Consider all subarrays starting 
# from first element 
for i in range(n): 

# Initialize count of elements 
# ending at j 
cnt = 0

# Consider all subarrays ending 
# at j 
for j in range(i, n): 

# If this subarray has exactly 
# k odd elements, then increment 
# result 
if (arr[j] % 2 == 1): 
cnt += 1

# If count becomes k, then 
# increment result 
if (cnt == k): 
res += 1

# Return result 
return res
var countSubarrays = function(arr, l, r) {
    // your code goes here
    let count = 0;
    for (let i = l; i <= r; i++) {
        for (let j = i; j <= r; j++) {
            let sub = arr.slice(i, j + 1);
            if (isValid(sub)) {
                count++;
            }
        }
    }
    return count;
};

var isValid = function(arr) {
    // your code goes here
    for (let i = 0; i < arr.length - 1; i++) {
        if (arr[i] > arr[i + 1]) {
            return false;
        }
    }
    return true;
};
int countSubarrays(vector& nums, int l, int r) 
    { 
        int n = nums.size(); 
        int cnt = 0; 
        for (int i = 0; i < n; i++) 
        { 
            int sum = nums[i]; 
            if (sum >= l && sum <= r) 
                cnt++; 
            for (int j = i+1; j < n; j++) 
            { 
                sum += nums[j]; 
                if (sum >= l && sum <= r) 
                    cnt++; 
            } 
        } 
        return cnt; 
    }
int countSubarrays(int[] nums, int l, int r) 
    { 
  
        // Left[i] stores count of  
        // subarrays starting from arr[i] 
        // such that arr[i] is part of  
        // that subarray 
        int[] left = new int[nums.Length]; 
          
        // Right[j] stores count of 
        // subarrays from arr[j] 
        // such that arr[j] is part 
        // of that subarray 
        int[] right = new int[nums.Length]; 
          
        // initialize left and right 
        // arrays as 1 
        for(int i=0;inums[j]) 
                left[i] = left[i]+left[j]; 
        } 
          
        // Fill right array 
        for(int j=nums.Length-2;j>=0;j--) 
        { 
            int i = j+1; 
              
            // if arr[j] is greater than arr[i] 
            // then there are at-least 
            // i-1 subarrays 
            // ending at arr[j] 
            // such that arr[j] is 
            // greater than arr[i] 
            if(nums[j]>nums[i]) 
                right[j] = right[j]+right[i]; 
        } 
          
        // Inversion Count will give 
        // the number of subarrays 
        // such that L <= i <= R 
        int inv_count = 0; 
          
        // traverse both arrays from 
        // start to end 
        for(int i=l;i<=r;i++) 
              
            // inv_count += left[i]*right[i]; 
            inv_count += (left[i]*right[i])%1000000007; 
              
        return inv_count; 
    }


Scroll to Top
[gravityforms id="5" description="false" titla="false" ajax="true"]