1207. Unique Number of Occurrences
Problem Description
You are given an array of integers arr
. Your task is to determine if the frequency of each unique value in the array is distinct.
In other words, count how many times each number appears in the array. If all these occurrence counts are different from each other, return true
. If any two numbers have the same occurrence count, return false
.
For example:
- If the array is
[1, 2, 2, 1, 1, 3]
, the number 1 appears 3 times, 2 appears 2 times, and 3 appears 1 time. Since the frequencies (3, 2, 1) are all different, the answer istrue
. - If the array is
[1, 2]
, both 1 and 2 appear exactly 1 time. Since two numbers have the same frequency, the answer isfalse
.
The solution uses a hash table to count the frequency of each number in the array, then checks if all frequency values are unique by comparing the number of distinct frequencies with the total number of unique elements.
Intuition
The key insight is that we need to check if all frequency counts are unique. This is essentially a two-step process:
- First, count how many times each number appears in the array
- Then, check if these counts themselves are all different
Think of it this way: if we have counts like {1: 3, 2: 2, 3: 1}
(meaning 1 appears 3 times, 2 appears 2 times, 3 appears 1 time), we need to verify that the values [3, 2, 1]
are all distinct.
The clever part is realizing that to check if all frequencies are unique, we can use a set. Sets automatically remove duplicates, so if we put all frequency values into a set and the set has the same size as the original collection of frequencies, then all frequencies must be unique.
For example:
- If frequencies are
[3, 2, 1]
, converting to a set gives{3, 2, 1}
with size 3, same as original - If frequencies are
[2, 2, 1]
, converting to a set gives{2, 1}
with size 2, different from original size 3
This leads to the elegant solution: len(set(cnt.values())) == len(cnt)
. If the number of unique frequencies equals the number of unique elements in the array, then each element has a distinct occurrence count.
Solution Approach
The solution uses a hash table approach to solve this problem efficiently.
Step 1: Count Frequencies
We use Python's Counter
from the collections module to create a hash table cnt
that counts the frequency of each number in the array. After this step, cnt
contains key-value pairs where the key is a number from the array and the value is how many times it appears.
For example, if arr = [1, 2, 2, 1, 1, 3]
, then cnt = {1: 3, 2: 2, 3: 1}
.
Step 2: Check Uniqueness of Frequencies
To verify if all frequencies are unique, we extract all the frequency values using cnt.values()
and convert them to a set using set(cnt.values())
. Since sets automatically eliminate duplicates, if any two elements had the same frequency, the set would be smaller than the original collection.
Step 3: Compare Sizes We compare the size of the set of frequencies with the size of the original counter:
len(set(cnt.values()))
gives us the number of unique frequencieslen(cnt)
gives us the number of distinct elements in the original array
If these two values are equal, it means each frequency value is unique, so we return true
. Otherwise, we return false
.
Time Complexity: O(n)
where n
is the length of the array, as we iterate through the array once to count frequencies.
Space Complexity: O(n)
in the worst case when all elements are unique, requiring space for the hash table to store all elements and their counts.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with the array [1, 2, 2, 1, 1, 3]
.
Step 1: Count the frequency of each element
We iterate through the array and count occurrences:
- 1 appears: at indices 0, 3, 4 → 3 times
- 2 appears: at indices 1, 2 → 2 times
- 3 appears: at index 5 → 1 time
Our frequency counter becomes: {1: 3, 2: 2, 3: 1}
Step 2: Extract the frequency values
From our counter, we get the values: [3, 2, 1]
Step 3: Check if all frequencies are unique
We convert the frequency values to a set: {3, 2, 1}
- Original number of unique elements:
len(cnt) = 3
(we have three distinct numbers: 1, 2, 3) - Number of unique frequencies:
len(set([3, 2, 1])) = 3
(all frequencies are different)
Step 4: Compare and return result
Since 3 == 3
, all frequencies are unique, so we return true
.
Counter-example: If we had [1, 2]
:
- Frequency counter:
{1: 1, 2: 1}
- Frequency values:
[1, 1]
- Set of frequencies:
{1}
(duplicates removed) len(set([1, 1])) = 1
butlen(cnt) = 2
- Since
1 ≠ 2
, we returnfalse
Solution Implementation
1from typing import List
2from collections import Counter
3
4class Solution:
5 def uniqueOccurrences(self, arr: List[int]) -> bool:
6 # Count the frequency of each element in the array
7 frequency_map = Counter(arr)
8
9 # Check if all frequencies are unique by comparing:
10 # - The number of unique frequencies (using set to remove duplicates)
11 # - The total number of elements with frequencies
12 # If they're equal, all frequencies are unique
13 return len(set(frequency_map.values())) == len(frequency_map)
14
1class Solution {
2 public boolean uniqueOccurrences(int[] arr) {
3 // Create a map to store the frequency of each element
4 Map<Integer, Integer> frequencyMap = new HashMap<>();
5
6 // Count occurrences of each element in the array
7 for (int element : arr) {
8 frequencyMap.merge(element, 1, Integer::sum);
9 }
10
11 // Check if all occurrence counts are unique
12 // by comparing the size of unique occurrence values with total number of elements
13 return new HashSet<>(frequencyMap.values()).size() == frequencyMap.size();
14 }
15}
16
1class Solution {
2public:
3 bool uniqueOccurrences(vector<int>& arr) {
4 // Step 1: Count the frequency of each element in the array
5 unordered_map<int, int> frequencyMap;
6 for (int& element : arr) {
7 ++frequencyMap[element];
8 }
9
10 // Step 2: Check if all frequencies are unique using a set
11 unordered_set<int> seenFrequencies;
12 for (auto& [key, frequency] : frequencyMap) {
13 // If this frequency has already been seen, frequencies are not unique
14 if (seenFrequencies.count(frequency)) {
15 return false;
16 }
17 // Add the current frequency to the set of seen frequencies
18 seenFrequencies.insert(frequency);
19 }
20
21 // All frequencies are unique
22 return true;
23 }
24};
25
1/**
2 * Determines if all elements in the array have unique occurrence counts
3 * @param arr - Input array of numbers
4 * @returns true if all occurrence counts are unique, false otherwise
5 */
6function uniqueOccurrences(arr: number[]): boolean {
7 // Map to store the frequency count of each number
8 const frequencyMap: Map<number, number> = new Map<number, number>();
9
10 // Count occurrences of each number in the array
11 for (const num of arr) {
12 const currentCount: number = frequencyMap.get(num) || 0;
13 frequencyMap.set(num, currentCount + 1);
14 }
15
16 // Check if all frequency values are unique
17 // by comparing the size of the map with the size of unique frequency values
18 const uniqueFrequencies: Set<number> = new Set<number>(frequencyMap.values());
19 return frequencyMap.size === uniqueFrequencies.size;
20}
21
Time and Space Complexity
Time Complexity: O(n)
- Creating the Counter object requires iterating through all
n
elements in the array to count occurrences:O(n)
cnt.values()
returns a view of the values inO(1)
time- Converting values to a set requires iterating through all unique counts (at most
n
values):O(k)
wherek
is the number of unique elements, andk ≤ n
len(set(cnt.values()))
andlen(cnt)
are bothO(1)
operations after the set is created- Overall time complexity:
O(n) + O(k) = O(n)
sincek ≤ n
Space Complexity: O(n)
- The Counter object stores at most
n
key-value pairs (in the worst case where all elements are unique):O(n)
- Creating a set from the values requires additional space for at most
k
unique occurrence counts, wherek ≤ n
:O(k)
- Overall space complexity:
O(n) + O(k) = O(n)
sincek ≤ n
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Misunderstanding the Problem Requirements
The Mistake: A common misunderstanding is thinking we need to check if all elements in the array are unique, rather than checking if all frequency counts are unique. Someone might incorrectly write:
def uniqueOccurrences(self, arr: List[int]) -> bool:
return len(set(arr)) == len(arr) # Wrong! This checks if elements are unique
The Fix: Focus on the frequencies, not the elements themselves. The correct approach counts occurrences first, then checks if those counts are unique.
Pitfall 2: Incorrect Frequency Comparison Logic
The Mistake: Some developers might try to compare frequencies incorrectly by iterating through and checking duplicates manually, leading to inefficient or buggy code:
def uniqueOccurrences(self, arr: List[int]) -> bool:
frequency_map = Counter(arr)
freq_list = list(frequency_map.values())
# Inefficient nested loop approach
for i in range(len(freq_list)):
for j in range(i + 1, len(freq_list)):
if freq_list[i] == freq_list[j]:
return False
return True
The Fix: Use a set to check uniqueness in O(n) time instead of O(n²) with nested loops. The set automatically handles duplicate detection.
Pitfall 3: Not Handling Edge Cases
The Mistake: Forgetting to consider edge cases like empty arrays or single-element arrays:
def uniqueOccurrences(self, arr: List[int]) -> bool:
if not arr: # What should we return for empty array?
return ???
frequency_map = Counter(arr)
return len(set(frequency_map.values())) == len(frequency_map)
The Fix: The given solution actually handles these cases correctly:
- Empty array:
Counter([])
returns an empty Counter, and bothlen(set())
andlen(Counter())
equal 0, returningTrue
- Single element: Returns
True
as there's only one frequency
Pitfall 4: Manual Frequency Counting Errors
The Mistake: Attempting to count frequencies manually instead of using Counter, which can lead to errors:
def uniqueOccurrences(self, arr: List[int]) -> bool:
frequency_map = {}
for num in arr:
frequency_map[num] += 1 # KeyError if num not in dictionary!
return len(set(frequency_map.values())) == len(frequency_map)
The Fix: Either use Counter
which handles this automatically, or properly initialize dictionary entries:
frequency_map = {} for num in arr: frequency_map[num] = frequency_map.get(num, 0) + 1
Which algorithm should you use to find a node that is close to the root of the tree?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!