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; }