Range Frequency Queries
MediumUpdated: Aug 2, 2025
Practice on:
Problem
Design a data structure to find the frequency of a given value in a given subarray.
The frequency of a value in a subarray is the number of occurrences of that value in the subarray.
Implement the RangeFreqQuery class:
RangeFreqQuery(int[] arr)Constructs an instance of the class with the given 0-indexed integer arrayarr.int query(int left, int right, int value)Returns the frequency ofvaluein the subarrayarr[left...right].
A subarray is a contiguous sequence of elements within an array. arr[left...right] denotes the subarray that contains the elements of nums between indices left and right (inclusive).
Examples
Example 1:
**Input**
["RangeFreqQuery", "query", "query"]
[[[12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]], [1, 2, 4], [0, 11, 33]]
**Output**
[null, 1, 2]
**Explanation**
RangeFreqQuery rangeFreqQuery = new RangeFreqQuery([12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]);
rangeFreqQuery.query(1, 2, 4); // return 1. The value 4 occurs 1 time in the subarray [33, 4]
rangeFreqQuery.query(0, 11, 33); // return 2. The value 33 occurs 2 times in the whole array.
Solution
Method 1 - Using Map of List
To solve this problem, we can use a HashMap to preprocess and store the indices of all occurrences of each number in the array. This will allow us to efficiently query the frequency of a value in a given subarray using binary search.
Here are key points:
- Data Structure:
- Use a
HashMap<Integer, List<Integer>>(ordefaultdictin Python) to map each value in the array to its list of indices. - For example, for the array
[1, 2, 1, 3, 1], the map would look like:{1: [0, 2, 4], 2: [1], 3: [3]}.
- Use a
- Preprocessing:
- Iterate through the array, and populate the map such that for each number, we store its list of indices.
- This step takes
O(n)time, wherenis the size of the array.
- Query Operation:
- To determine the number of occurrences of a value in
arr[left...right], use the precomputed indices from the HashMap. - Use binary search (via
Collections.binarySearchin Java orbisectin Python) to find:- The smallest index in the list that is
>= left. - The largest index in the list that is
<= right.
- The smallest index in the list that is
- The difference between these indices gives the frequency of the value in the subarray.
- To determine the number of occurrences of a value in
Code
Java
class RangeFreqQuery {
private Map<Integer, List<Integer>> indexMap;
public RangeFreqQuery(int[] arr) {
indexMap = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
indexMap.computeIfAbsent(arr[i], k -> new ArrayList<>()).add(i);
}
}
public int query(int left, int right, int value) {
if (!indexMap.containsKey(value)) return 0;
List<Integer> indices = indexMap.get(value);
int start = Collections.binarySearch(indices, left);
int end = Collections.binarySearch(indices, right);
// Adjust positions to account for binarySearch contract
if (start < 0) start = -start - 1;
if (end < 0) end = -end - 2;
return end - start + 1;
}
}
Python
class RangeFreqQuery:
def __init__(self, arr: List[int]) -> None:
self.idx_map: Dict[int, List[int]] = {}
for i, val in enumerate(arr):
if val not in self.idx_map:
self.idx_map[val] = []
self.idx_map[val].append(i)
def query(self, left: int, right: int, value: int) -> int:
if value not in self.idx_map:
return 0
indices = self.idx_map[value]
start = bisect_left(indices, left)
end = bisect_right(indices, right) - 1
return max(0, end - start + 1)
Complexity
- ⏰ Time complexity
- Preprocessing:
O(n) - Query:
- Binary searches (
O(log k)each) to locate the range of indices, wherekis the total number of occurrences of the value in the array. - Hence, query complexity is
O(log k).
- Binary searches (
- Preprocessing:
- 🧺 Space complexity:
O(n)