Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Javascript Program for Range Queries for Frequencies of array elements
We are given an array that will contain integers and another array will be given that will contain the queries and each query represents the range that we are given by the leftmost and the rightmost index in the array and an element. For that range or the subarray, we have to find the frequency of the given element present in that range.
The frequency of the elements means that we have to tell for each integer present in that range how many times it occurs. For example ?
If, the given array is: [5, 2, 5, 3, 1, 5, 2, 2, 5]
The queries array is: [[0, 4, 5], [1, 7, 2]]
For the first query, the subarray is: 5, 2, 5, 3, and 1, so the frequency of 5 is 2.
For the second query, the subarray is 2, 5, 3, 1, 5, 2, and 2, so the frequency of 2 is 3.
Approach
To solve this problem, we are going to follow these steps ?
First, we will create a separate function to call for each query and pass the query elements as the parameters.
Inside the function, we will get the length of the array to traverse over it and will create a variable count to store the frequency of the given element.
We will use the for loop to traverse in the given range and at each iteration, if the current array element is equal to the given element, then we will increase the count.
At the end, we will print the current count for the given element.
Method 1: Simple Range Traversal
This approach directly traverses the given range for each query to count the frequency of the target element.
// function to answer their queries
function findFre(arr, L, R, ele) {
var n = arr.length;
var count = 0;
// traversing over the array in given range
for (var i = L; i <= R; i++) {
if (arr[i] == ele) {
count++;
}
}
console.log("The frequency of " + ele + " in range [" + L + ", " + R + "] is: " + count);
return count;
}
// defining array
var arr = [5, 2, 5, 3, 1, 5, 2, 2, 5];
console.log("Array:", arr);
var queries = [[0, 4, 5], [1, 7, 2]];
console.log("Queries:", queries);
// processing each query
for (var i = 0; i < queries.length; i++) {
findFre(arr, queries[i][0], queries[i][1], queries[i][2]);
}
Array: [5, 2, 5, 3, 1, 5, 2, 2, 5] Queries: [[0, 4, 5], [1, 7, 2]] The frequency of 5 in range [0, 4] is: 2 The frequency of 2 in range [1, 7] is: 3
Time and Space Complexity
The time complexity of the above code is O(Q*N) where Q is the number of queries and N is the size of the array. Time complexity is the factor of N because we are traversing over the array in the given range, for each query.
The space complexity of the above code is O(1) as we are not using any extra space to store anything.
Method 2: Optimized with Index Mapping
For better performance when dealing with multiple queries, we can preprocess the array to store indices of each element. This reduces query time to O(log N) using binary search.
var store = null;
function lowerBound(arr, target) {
var left = 0, right = arr.length;
while (left < right) {
var mid = Math.floor((left + right) / 2);
if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
function upperBound(arr, target) {
var left = 0, right = arr.length;
while (left < right) {
var mid = Math.floor((left + right) / 2);
if (arr[mid] <= target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
function findFreOptimized(arr, L, R, ele) {
if (!store.has(ele)) {
console.log("The frequency of " + ele + " in range [" + L + ", " + R + "] is: 0");
return 0;
}
var indices = store.get(ele);
var leftIdx = lowerBound(indices, L);
var rightIdx = upperBound(indices, R);
var count = rightIdx - leftIdx;
console.log("The frequency of " + ele + " in range [" + L + ", " + R + "] is: " + count);
return count;
}
// defining array
var arr = [5, 2, 5, 3, 1, 5, 2, 2, 5];
console.log("Array:", arr);
// preprocessing: store indices of each element
store = new Map();
for (var i = 0; i < arr.length; i++) {
if (!store.has(arr[i])) {
store.set(arr[i], []);
}
store.get(arr[i]).push(i);
}
var queries = [[0, 4, 5], [1, 7, 2]];
console.log("Queries:", queries);
// processing queries with optimized approach
for (var i = 0; i < queries.length; i++) {
findFreOptimized(arr, queries[i][0], queries[i][1], queries[i][2]);
}
Array: [5, 2, 5, 3, 1, 5, 2, 2, 5] Queries: [[0, 4, 5], [1, 7, 2]] The frequency of 5 in range [0, 4] is: 2 The frequency of 2 in range [1, 7] is: 3
Comparison
| Method | Time Complexity | Space Complexity | Best For |
|---|---|---|---|
| Simple Traversal | O(Q * N) | O(1) | Few queries |
| Index Mapping | O(Q * log N) | O(N) | Many queries |
Key Points
The simple approach is suitable when you have fewer queries or limited memory.
The optimized approach with preprocessing is better for multiple queries on the same array.
Binary search is used in the optimized version to find the count of elements in a given range efficiently.
Conclusion
We implemented two JavaScript approaches for range frequency queries. The simple method offers O(1) space with O(Q*N) time, while the optimized approach trades space for better query performance at O(Q*log N) time. Choose based on your query frequency and memory constraints.
