Skip to main content

Range Frequency Queries - Solution & Explanation

MediumArrayHash TableBinary SearchDesign23 min readAsked at: Microsoft, Quora
Practice this problem

Problem Statement

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 array arr.
  • int query(int left, int right, int value) Returns the frequency of value in the subarray arr[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).

 

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.

 

Constraints:

  • 1 <= arr.length <= 105
  • 1 <= arr[i], value <= 104
  • 0 <= left <= right < arr.length
  • At most 105 calls will be made to query

Approach Overview

Problem Overview: You receive an integer array and must repeatedly answer queries of the form (left, right, value). Each query asks how many times value appears between indices left and right inclusive. The challenge is supporting many queries efficiently without scanning the entire range every time.

Approach 1: Brute Force Scan (O(n) per query, O(1) space)

The simplest method directly scans the subarray from left to right. For each index, compare the element with value and increment a counter if it matches. This requires no preprocessing and no additional memory beyond a counter variable. However, every query may examine up to n elements, leading to O(n) time per query and poor performance when the number of queries is large. This approach mainly demonstrates the baseline before applying better array query techniques.

Approach 2: Hash Map Preprocessing + Binary Search (Preprocess O(n), Query O(log k), Space O(n))

A more efficient strategy preprocesses the array by storing the indices of each value. Build a HashMap<value, List<indices>> where every list contains the sorted positions where that value occurs. During a query, retrieve the list for value and use binary search to find the first index >= left and the first index > right. The difference between these positions gives the frequency inside the range.

The key insight: indices are naturally sorted as you traverse the array once. That allows fast range counting using two binary searches instead of scanning the subarray. If a value appears k times overall, the query cost becomes O(log k). Preprocessing the map takes O(n) time and O(n) memory. This pattern is common in problems combining hash tables with range queries.

Some advanced solutions also use a segment tree or other range-query structures, but they are unnecessary here because the value-index mapping already provides efficient lookups.

Recommended for interviews: The hash map + binary search approach is the expected solution. Interviewers want to see that you avoid repeated scans and instead preprocess positions for fast queries. Mentioning the brute force approach first shows understanding of the baseline, while implementing the indexed map demonstrates practical optimization skills.

Approach 1: Brute Force Approach

In this approach, for each query, we will iterate over the subarray to count the occurrences of the given value. Although this approach is straightforward and easy to implement, it is inefficient since each query will take O(n) time in the worst case, where n is the length of the subarray.

The implementation iterates through the range specified by left and right and counts how many times value appears. This is done inside the countFrequency function.

Code

C

C++

Java

Python

C#

JavaScript

Complexity

Time Complexity: O(n) per query, where n is the length of the subarray from left to right.
Space Complexity: O(1), as no additional data structures are used.

Try this approach in the editor →

Approach 2: Hash Map Preprocessing

In this approach, the array is preprocessed using a hash map, where each value maps to a list of its indices in the array. During a query, we can efficiently count the frequencies using binary search on the stored indices, making the query process much faster.

This C implementation relies on a hypothetical hashmap utility. Preprocessing involves storing indices for each value, allowing quick binary search within those indices during queries.

Code

C

C++

Java

Python

C#

JavaScript

Complexity

Time Complexity: O(n) for preprocess and O(log k) for queries, where k is the number of stored indices.
Space Complexity: O(n), storing indices for potential values.

Try this approach in the editor →

Approach 3: Hash Table + Binary Search

We use a hash table g to store the array of indices corresponding to each value. In the constructor, we traverse the array arr, adding the index corresponding to each value to the hash table.

In the query function, we first check whether the given value exists in the hash table. If it does not exist, it means that the value does not exist in the array, so we directly return 0. Otherwise, we get the index array idx corresponding to the value. Then we use binary search to find the first index l that is greater than or equal to left, and the first index r that is greater than right. Finally, we return r - l.

In terms of time complexity, the time complexity of the constructor is O(n), and the time complexity of the query function is O(log n). The space complexity is O(n). Where n is the length of the array.

Code

Python

Java

C++

Go

TypeScript

Rust

JavaScript

C#

Try this approach in the editor →

Complexity Comparison

ApproachComplexity
Brute Force Approach

Time Complexity: O(n) per query, where n is the length of the subarray from left to right.
Space Complexity: O(1), as no additional data structures are used.

Hash Map Preprocessing

Time Complexity: O(n) for preprocess and O(log k) for queries, where k is the number of stored indices.
Space Complexity: O(n), storing indices for potential values.

Hash Table + Binary Search—

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Brute Force ScanO(n) per queryO(1)Small arrays or very few queries where preprocessing is unnecessary
Hash Map + Binary SearchPreprocess O(n), Query O(log k)O(n)Best general solution when many queries must be answered efficiently

Video Solution

Range Frequency Queries | LeetCode Weekly contest 268 | Most popular concept in CP • Aditya Rajiv • 2,236 views views

Watch 9 more video solutions →

Frequently Asked Questions

Is Range Frequency Queries easy or hard?
Range Frequency Queries is considered a Medium difficulty problem. The brute force idea is straightforward, but the intended solution requires recognizing that storing indices and applying binary search enables efficient repeated queries.
Range Frequency Queries Python/Java solution
In Python, use a dictionary mapping values to lists of indices and the bisect module for binary search. In Java, use a HashMap<Integer, List<Integer>> and Collections.binarySearch or custom lower/upper bound logic. Both implementations achieve O(n) preprocessing and O(log k) per query.
How to solve Range Frequency Queries in O(n)?
Build a map from each value to a sorted list of its indices by scanning the array once. This preprocessing step takes O(n). Each query then uses two binary searches on that list to count how many indices fall between left and right, giving O(log k) query time.
What is the best approach for Range Frequency Queries?
The most efficient solution preprocesses the array using a hash map that stores the indices of each value. For a query (left, right, value), retrieve the index list for that value and run two binary searches to find how many indices fall inside the range. Preprocessing takes O(n) time and each query runs in O(log k), where k is the number of occurrences of that value.
Is Range Frequency Queries asked at Google/Amazon/Meta?
Range frequency style problems appear in interviews at large tech companies because they test data structure design and query optimization. Variations involving index preprocessing, binary search, or segment trees are commonly discussed in Google, Amazon, and Meta interview prep.
What data structure is used in Range Frequency Queries?
The typical solution uses a hash map that maps each value to a sorted list of indices where it appears. Binary search is then used on those lists to count elements within a given index range efficiently.
What is the time complexity of Range Frequency Queries?
The optimal implementation runs in O(n) preprocessing time and O(log k) per query using binary search on the stored index list for each value. Space complexity is O(n) because every index from the array is stored in the hash map.

Ready to solve this problem?

Practice Range Frequency Queries with our built-in code editor and test cases.

Practice on FleetCode