title: Unique Number of Occurrences slug: unique-number-of-occurrences difficulty: easy leetcode_id: 1207 leetcode_url: https://leetcode.com/problems/unique-number-of-occurrences/ categories: - arrays - hash-tables patterns: - prefix-sum description: | Given an array of integers `arr`, return `true` *if the number of occurrences of each value in the array is **unique***, or `false` *otherwise*. In other words, no two different values in the array should appear the same number of times. constraints: | - `1 <= arr.length <= 1000` - `-1000 <= arr[i] <= 1000` examples: - input: "arr = [1,2,2,1,1,3]" output: "true" explanation: "The value 1 has 3 occurrences, 2 has 2 occurrences, and 3 has 1 occurrence. No two values have the same number of occurrences." - input: "arr = [1,2]" output: "false" explanation: "Both 1 and 2 appear exactly once, so their occurrence counts are not unique." - input: "arr = [-3,0,1,-3,1,1,1,-3,10,0]" output: "true" explanation: "The value 1 appears 4 times, -3 appears 3 times, 0 appears 2 times, and 10 appears 1 time. All counts are unique." explanation: intuition: | This problem asks us to verify a **uniqueness property about frequencies**, not about the values themselves. Think of it like this: imagine you're organising a party and counting how many guests ordered each dish. You want to check if every dish has a *different* number of orders — no two dishes should be equally popular. The key insight is that this is a **two-step counting problem**: 1. First, count how many times each value appears (value → frequency) 2. Then, check if all those frequencies are unique (no duplicates in the frequency list) A hash map is perfect for the first step (counting), and a set is perfect for the second step (checking uniqueness). Since sets automatically reject duplicates, we can simply compare the number of unique frequencies to the total number of frequencies. approach: | We solve this using a **Hash Map + Set Approach**: **Step 1: Count occurrences of each value** - Create a hash map (dictionary) to store each value and its count - Iterate through the array, incrementing the count for each value - After this step, we have a mapping like `{1: 3, 2: 2, 3: 1}` for the first example   **Step 2: Extract the frequency counts** - Get all the count values from the hash map - For the first example, this gives us `[3, 2, 1]`   **Step 3: Check if all frequencies are unique** - Convert the list of frequencies to a set (which removes duplicates) - Compare the size of the set to the size of the original frequency list - If they're equal, all frequencies were unique; if the set is smaller, there were duplicates   **Step 4: Return the result** - Return `True` if the lengths match, `False` otherwise common_pitfalls: - title: Confusing Value Uniqueness with Frequency Uniqueness description: | The problem asks if the **occurrence counts** are unique, not if the values themselves are unique. For example, `[1, 2]` has all unique values, but both values appear exactly once. Since the frequencies `[1, 1]` are not unique, the answer is `false`. Make sure you're checking uniqueness of the *counts*, not the original array elements. wrong_approach: "Checking if array values are unique" correct_approach: "Counting frequencies, then checking if those frequencies are unique" - title: Using a List Instead of a Set description: | Some solutions try to check for duplicate frequencies by iterating through a list and comparing elements. This works but is unnecessarily complex. Using a set is the idiomatic way to check for uniqueness — just compare `len(frequencies)` with `len(set(frequencies))`. wrong_approach: "Nested loops to find duplicate frequencies" correct_approach: "Convert to set and compare lengths" - title: Forgetting Edge Cases description: | Consider edge cases: - Single element array: `[5]` → frequency is `{5: 1}` → only one count → return `true` - All same elements: `[2, 2, 2]` → frequency is `{2: 3}` → only one count → return `true` Both cases have trivially unique frequencies since there's only one distinct value. key_takeaways: - "**Two-phase counting pattern**: Many problems require counting elements first, then analysing the counts themselves" - "**Set for uniqueness**: Converting a collection to a set and comparing lengths is the standard way to check for duplicates" - "**Hash map for frequency**: `Counter` or dictionary counting is a fundamental pattern for frequency-based problems" - "**Problem decomposition**: Breaking 'unique occurrences' into 'count frequencies' + 'check uniqueness' makes the solution clear" time_complexity: "O(n). We iterate through the array once to count frequencies, then iterate through the frequency values (at most n unique values) to build the set." space_complexity: "O(n). In the worst case, all elements are unique, so the hash map stores n key-value pairs, and the set stores n frequency values." solutions: - approach_name: Hash Map and Set is_optimal: true code: | from collections import Counter def unique_occurrences(arr: list[int]) -> bool: # Step 1: Count occurrences of each value frequency = Counter(arr) # Step 2: Get all the count values counts = frequency.values() # Step 3: Check if all counts are unique # If set size equals list size, no duplicates exist return len(counts) == len(set(counts)) explanation: | **Time Complexity:** O(n) — One pass to count, one pass to build the set. **Space Complexity:** O(n) — Hash map and set each store at most n elements. We use Python's `Counter` for concise frequency counting, then leverage the set's uniqueness property. If converting counts to a set reduces the size, there were duplicate frequencies. - approach_name: Manual Dictionary Counting is_optimal: true code: | def unique_occurrences(arr: list[int]) -> bool: # Count occurrences using a dictionary frequency = {} for num in arr: # Increment count, defaulting to 0 if not seen frequency[num] = frequency.get(num, 0) + 1 # Get the frequency counts counts = list(frequency.values()) # Check uniqueness: set removes duplicates return len(counts) == len(set(counts)) explanation: | **Time Complexity:** O(n) — Same as the Counter approach. **Space Complexity:** O(n) — Same space usage. This approach shows the manual counting logic without relying on `Counter`. It's useful for understanding what happens under the hood or when `Counter` isn't available. - approach_name: Sorting Approach is_optimal: false code: | def unique_occurrences(arr: list[int]) -> bool: # Count occurrences frequency = {} for num in arr: frequency[num] = frequency.get(num, 0) + 1 # Sort the counts counts = sorted(frequency.values()) # Check adjacent elements for duplicates for i in range(1, len(counts)): if counts[i] == counts[i - 1]: return False return True explanation: | **Time Complexity:** O(n log n) — Due to sorting the frequency counts. **Space Complexity:** O(n) — Storing frequencies and sorted counts. This approach sorts the counts and checks for adjacent duplicates. While correct, sorting adds unnecessary overhead compared to using a set. Included to show an alternative that doesn't use sets.