What Is Frequency Counting?
Frequency counting is a common data structure and algorithm technique used to determine how many times each value appears in a collection of data.
Instead of repeatedly scanning the original collection for every value, frequency counting stores each value together with the number of times it has appeared. A HashMap or similar key-value structure is commonly used for this purpose.
const numbers = [2, 4, 2, 7, 4, 2];
2 → 3
4 → 2
7 → 1
The value becomes the key, while its frequency becomes the associated value.
Why Frequency Counting Matters
Frequency counting is useful whenever an application or algorithm needs to understand how often values occur. It can replace repeated searches with a single pass through the input in many situations.
- Counting duplicate values.
- Finding the most frequent element.
- Finding unique or non-repeating values.
- Counting characters in a string.
- Comparing whether two collections contain the same frequencies.
- Grouping records by a property.
- Analyzing user activity or event data.
- Solving coding interview problems efficiently.
The Basic Frequency Counting Pattern
The most common pattern is to create an empty map, process each element, and increment its stored count.
const numbers = [10, 20, 10, 30, 20, 10];
const frequency = new Map();
for (const number of numbers) {
frequency.set(
number,
(frequency.get(number) ?? 0) + 1
);
}
console.log(frequency);
The expression frequency.get(number) ?? 0 handles the first occurrence.
If the number has not been stored yet, its starting count is treated as zero.
Frequency Counting Step by Step
Consider the input:
[3, 5, 3, 7, 5, 3]
Process each value one at a time:
| Element | Frequency After Processing |
|---|---|
| 3 | { 3: 1 } |
| 5 | { 3: 1, 5: 1 } |
| 3 | { 3: 2, 5: 1 } |
| 7 | { 3: 2, 5: 1, 7: 1 } |
| 5 | { 3: 2, 5: 2, 7: 1 } |
| 3 | { 3: 3, 5: 2, 7: 1 } |
The final result tells us exactly how frequently each value occurred.
Counting Frequencies with a JavaScript Map
JavaScript's Map is well suited to frequency counting because it provides
key-value storage and efficient average-case lookup.
function countFrequency(values) {
const frequency = new Map();
for (const value of values) {
const currentCount = frequency.get(value) ?? 0;
frequency.set(value, currentCount + 1);
}
return frequency;
}
const result = countFrequency([
"JavaScript",
"Python",
"JavaScript",
"Java",
"Python"
]);
for (const [language, count] of result) {
console.log(language, count);
}
Counting Character Frequency
Frequency counting is frequently applied to strings. Each character can become a key and its number of occurrences can be stored as the value.
function countCharacters(text) {
const frequency = new Map();
for (const character of text) {
frequency.set(
character,
(frequency.get(character) ?? 0) + 1
);
}
return frequency;
}
const result = countCharacters("banana");
console.log(result);
// b → 1
// a → 3
// n → 2
This pattern is useful for character analysis, duplicate detection, anagram problems, and other string-processing tasks.
Ignoring Case When Counting
Sometimes uppercase and lowercase characters should be treated as the same value. Normalize the input before counting.
function countCharacters(text) {
const frequency = new Map();
for (const character of text.toLowerCase()) {
frequency.set(
character,
(frequency.get(character) ?? 0) + 1
);
}
return frequency;
}
console.log(countCharacters("JavaScript"));
The normalization step is part of the problem definition. If uppercase and lowercase characters should remain different, the input should not be converted to lowercase.
Counting Words
The same technique can count words instead of individual characters.
function countWords(sentence) {
const words = sentence.toLowerCase().split(/\s+/);
const frequency = new Map();
for (const word of words) {
frequency.set(
word,
(frequency.get(word) ?? 0) + 1
);
}
return frequency;
}
const result = countWords(
"code learn code practice learn code"
);
console.log(result);
Finding the Most Frequent Element
Once frequencies have been calculated, the map can be traversed to find the value with the highest count.
function mostFrequent(numbers) {
const frequency = new Map();
for (const number of numbers) {
frequency.set(
number,
(frequency.get(number) ?? 0) + 1
);
}
let result = null;
let highestFrequency = 0;
for (const [number, count] of frequency) {
if (count > highestFrequency) {
highestFrequency = count;
result = number;
}
}
return result;
}
console.log(
mostFrequent([4, 2, 4, 7, 2, 4, 9])
);
// 4
If multiple values have the same highest frequency, the returned value depends on the tie-breaking logic. The example keeps the first value encountered with the highest count.
Finding the First Unique Element
Frequency counting can also identify elements that appear exactly once. First calculate the frequencies, then scan the original collection again.
function firstUnique(numbers) {
const frequency = new Map();
for (const number of numbers) {
frequency.set(
number,
(frequency.get(number) ?? 0) + 1
);
}
for (const number of numbers) {
if (frequency.get(number) === 1) {
return number;
}
}
return null;
}
console.log(
firstUnique([4, 7, 4, 9, 7, 10])
);
// 9
Frequency Counting for Duplicate Detection
If an element has a frequency greater than one, it is duplicated. However, if the requirement is only to determine whether a duplicate exists, a HashSet can often solve the problem without storing complete frequencies.
function hasDuplicate(values) {
const seen = new Set();
for (const value of values) {
if (seen.has(value)) {
return true;
}
seen.add(value);
}
return false;
}
console.log(hasDuplicate([10, 20, 30, 20]));
// true
Use a frequency map when the actual counts matter. Use a Set when you only need membership or duplicate detection.
Comparing Two Collections by Frequency
Two collections can contain the same values but in different orders. Frequency counting provides a way to compare their contents without requiring the elements to appear in the same sequence.
function sameFrequencies(first, second) {
if (first.length !== second.length) {
return false;
}
const frequency = new Map();
for (const value of first) {
frequency.set(
value,
(frequency.get(value) ?? 0) + 1
);
}
for (const value of second) {
const count = frequency.get(value);
if (!count) {
return false;
}
frequency.set(value, count - 1);
}
return true;
}
console.log(
sameFrequencies(
["a", "b", "a", "c"],
["c", "a", "b", "a"]
)
);
// true
Frequency Counting and Anagrams
Anagrams contain the same characters with the same frequencies, although their order differs. Frequency counting can therefore be used to compare strings efficiently.
function areAnagrams(first, second) {
if (first.length !== second.length) {
return false;
}
const frequency = new Map();
for (const character of first) {
frequency.set(
character,
(frequency.get(character) ?? 0) + 1
);
}
for (const character of second) {
const count = frequency.get(character);
if (!count) {
return false;
}
frequency.set(character, count - 1);
}
return true;
}
console.log(areAnagrams("listen", "silent"));
// true
console.log(areAnagrams("hello", "world"));
// false
Frequency Counting with Objects
A JavaScript object can also be used as a frequency table when the keys are suitable property keys.
const numbers = [1, 2, 1, 3, 2, 1];
const frequency = {};
for (const number of numbers) {
frequency[number] = (frequency[number] ?? 0) + 1;
}
console.log(frequency);
// { 1: 3, 2: 2, 3: 1 }
For general-purpose key-value data, especially when keys can be values other than strings
or when explicit map operations are useful, JavaScript's Map is often a
clearer choice.
Frequency Counting for Object Properties
Frequency counting is not limited to primitive values. You can count occurrences based on a property of objects.
const users = [
{ name: "John", role: "Developer" },
{ name: "Maya", role: "Designer" },
{ name: "Alex", role: "Developer" },
{ name: "Sara", role: "Tester" },
{ name: "David", role: "Developer" }
];
const roleFrequency = new Map();
for (const user of users) {
roleFrequency.set(
user.role,
(roleFrequency.get(user.role) ?? 0) + 1
);
}
console.log(roleFrequency);
// Developer → 3
// Designer → 1
// Tester → 1
Grouping Values Using Frequency Data
A related pattern is grouping records by a shared property. Instead of storing a number as the value, the map can store an array of matching records.
const users = [
{ name: "John", role: "Developer" },
{ name: "Maya", role: "Designer" },
{ name: "Alex", role: "Developer" }
];
const groups = new Map();
for (const user of users) {
if (!groups.has(user.role)) {
groups.set(user.role, []);
}
groups.get(user.role).push(user.name);
}
console.log(groups.get("Developer"));
// ["John", "Alex"]
This is a broader hash-based grouping pattern. The map key identifies a category, while the associated value contains the data belonging to that category.
Frequency Counting Complexity
Suppose there are n elements in the input and the frequency map provides
O(1) average insertion and lookup.
- Building the frequency map: O(n) average time.
- Traversing the frequency map: O(k), where k is the number of unique values.
- Typical additional space: O(k).
Since k cannot exceed n, the additional space is commonly
described as O(n) in the worst case.
Why Frequency Counting Can Improve an Algorithm
Consider checking every pair of elements to determine whether duplicates exist. Comparing every pair requires O(n²) time.
A hash-based approach can process each element once and remember what has already been encountered, giving O(n) average time for duplicate detection.
// Repeated pair comparisons
// O(n²)
// HashSet membership approach
// O(n) average
This is one of the most important patterns to recognize in data structure and coding interview problems: trade additional memory for faster lookup.
Frequency Counting vs Sorting
Sorting is another way to analyze repeated values, but it changes the ordering of the data or requires a sorted copy.
| Approach | Typical Time | Additional Space | Useful When |
|---|---|---|---|
| HashMap / Map | O(n) average | O(k) | Fast frequency lookup is important |
| Sorting | Typically O(n log n) | Depends on sorting approach | Order or sorted structure is useful |
Common Frequency Counting Mistakes
Forgetting the First Occurrence
A value may not exist in the map when it is encountered for the first time. Initialize its frequency to zero before incrementing it.
frequency.set(
value,
(frequency.get(value) ?? 0) + 1
);
Using a Set When Counts Are Required
A Set tells you whether a value exists, but it does not store how many times the value appeared. Use a frequency map when the count itself matters.
Ignoring Input Normalization
Requirements may treat values such as JavaScript and
javascript as equivalent. Normalize the input only when the problem
requires case-insensitive or otherwise normalized comparison.
Counting the Wrong Property
When processing objects, identify the exact property that defines the category being counted. For example, users may need to be counted by role, department, country, or subscription type.
Frequency Counting in Coding Interviews
Frequency counting is a fundamental interview pattern. When a problem contains repeated values, character comparisons, duplicates, or "how many times" language, a hash-based frequency table is often worth considering.
- Count repeated numbers.
- Count characters in a string.
- Check whether two strings are anagrams.
- Find the first non-repeating character.
- Find the most frequent element.
- Compare two collections by frequency.
- Group records by a property.
- Track occurrences while processing a stream of data.
A Useful Frequency Counting Workflow
When you encounter a frequency-based problem, break it into a few simple steps.
- Identify what should be counted.
- Choose the key for the frequency table.
- Create a HashMap or equivalent map.
- Process the input and increment each key's count.
- Use the resulting frequencies to answer the actual problem.
- Check whether normalization or a specific tie-breaking rule is required.
Key Takeaways
- Frequency counting records how many times each value occurs.
- A HashMap or JavaScript
Mapis commonly used to store frequencies. - The basic pattern is to increment a value's count as each element is processed.
- Frequency counting can solve many problems in O(n) average time.
- A HashSet is better when only membership or duplicate detection is required.
- Frequency maps are useful for strings, arrays, objects, and grouped data.
- Frequency counting is a common pattern in coding interviews and real-world data processing.
- Always consider input normalization and the exact definition of equality.