Skip to content
← All posts

Finding the Users Active Minutes: Hash Map Counting

5 min read
leetcodeproblemmediumarrayshash-map

Finding the Users Active Minutes is LeetCode problem 1817, a medium-difficulty exercise in hash map grouping. You are given a list of log entries where each entry records a user ID and a minute timestamp. Your job is to figure out how many users have exactly 1 unique active minute, how many have exactly 2, and so on up to k.

The tricky part is that duplicate entries for the same user and minute should only count once. That detail pushes you toward a set-based approach.

Example 1: logs = [[0,5],[1,2],[0,2],[0,5],[1,3]], k = 5

Output: [0, 2, 0, 0, 0]

User 0 was active during minutes 5 and 2 (the second [0,5] is a duplicate), so their UAM is 2. User 1 was active during minutes 2 and 3, so their UAM is also 2. Two users have UAM equal to 2, so answer[1] = 2.

Example 2: logs = [[1,1],[2,2],[2,3]], k = 4

Output: [1, 1, 0, 0]

User 1 has UAM = 1, user 2 has UAM = 2. One user at each count.

Input logs[0,5][1,2][0,2][0,5][1,3]Group unique minutes by user (hash map of sets)User 052UAM = 2User 123UAM = 2[0,5] appears twicebut only counted onceCount users per UAM value (answer array, k = 5)0j=12j=20j=30j=40j=52 usershave UAM=2
Collect unique minutes per user with a hash map of sets, then count how many users share each UAM value. The duplicate [0,5] entry is ignored by the set.

The approach

The problem has two phases, and each one maps directly to a data structure:

  1. Collect unique minutes per user. Build a hash map where keys are user IDs and values are sets of minutes. Every time you process a log entry, add the minute to that user's set. Because sets ignore duplicates, you never need to check whether a minute was already recorded.

  2. Count the frequency of each UAM value. Once the map is built, iterate over its values. For each user, the size of their set is their UAM. Increment the corresponding position in an answer array of size k.

That is the entire algorithm. One pass to build the map, one pass to read it.

Using a defaultdict(set) in Python eliminates the need to check whether a user key already exists. Every new user automatically starts with an empty set, keeping the loop body clean.

The code

from collections import defaultdict

def findingUsersActiveMinutes(logs, k):
    user_minutes = defaultdict(set)
    for user_id, minute in logs:
        user_minutes[user_id].add(minute)

    answer = [0] * k
    for minutes_set in user_minutes.values():
        uam = len(minutes_set)
        if uam <= k:
            answer[uam - 1] += 1

    return answer

Here is what happens step by step:

  1. user_minutes = defaultdict(set) creates a hash map that auto-initializes missing keys to empty sets.
  2. The first loop processes every log entry. For each [user_id, minute] pair, it adds minute to the set for user_id. Duplicates are silently ignored by the set.
  3. answer = [0] * k initializes a result array of size k, filled with zeros.
  4. The second loop iterates over every user's set. The length of the set is the user's UAM. We increment answer[uam - 1] because the answer array is 1-indexed (UAM of 1 maps to index 0).
  5. The guard if uam <= k is technically unnecessary given the problem constraints, but it makes the code defensive against edge cases.

Visual walkthrough

Let's trace through the full example with logs = [[0,5],[1,2],[0,2],[0,5],[1,3]] and k = 5. Watch how the hash map of sets builds up and how the answer array gets populated at the end.

Step 1: Initialize a hash map where each key is a user ID and each value is a set of minutes

Processing each log entry:[0, 5]→ map[0] = {5}[1, 2]→ map[1] = {2}[0, 2]→ map[0] = {5, 2}[0, 5]→ map[0] = {5, 2} (5 already in set, no change)[1, 3]→ map[1] = {2, 3}

Using a set automatically handles deduplication. When we see [0,5] a second time, the set for user 0 stays {5, 2}.

Step 2: Compute the UAM for each user by taking the size of their set

UserUnique minutesUAM0{5, 2}21{2, 3}2

The set size gives us the number of unique minutes. User 0 has |{5, 2}| = 2 and user 1 has |{2, 3}| = 2.

Step 3: Build the answer array of size k by counting users with each UAM

Counting:User 0: UAM = 2→ answer[2 - 1] += 1 → answer[1] = 1User 1: UAM = 2→ answer[2 - 1] += 1 → answer[1] = 2Final answer array:02000

Initialize answer = [0, 0, 0, 0, 0]. User 0 has UAM = 2, so answer[1] += 1. User 1 also has UAM = 2, so answer[1] += 1. Final answer: [0, 2, 0, 0, 0].

After processing all five log entries, the map has two users with UAM = 2. That count goes into answer[1], giving us [0, 2, 0, 0, 0].

Complexity analysis

ApproachTimeSpace
Hash map of setsO(n)O(n)

Here n is the number of log entries. Each log entry is processed exactly once during the map-building phase, and each set insertion is O(1) on average. The second pass over the map visits each user once, which is at most n users. The answer array takes O(k) space, but since k is bounded by the problem, the dominant space cost is the hash map storing up to n entries.

Building blocks

Hash map of sets for deduplication

Many problems ask you to group items by some key while ignoring duplicates within each group. The pattern is always the same: use a hash map where the value type is a set. This shows up in problems like group anagrams (where you group words by sorted key) and finding duplicates across categories. The set handles uniqueness, the map handles grouping, and together they give you both in one clean pass.

Frequency counting with an output array

After you have computed a per-item metric (in this case, UAM per user), you often need to count how many items share each metric value. The standard technique is to allocate an array of the right size and use the metric as an index. This is the same idea behind counting sort, degree-sequence problems in graph theory, and bucket-based frequency analysis.

Edge cases

All logs for one user. If every entry shares the same user ID, the map has a single key. The answer array will have a 1 at position uam - 1 and zeros everywhere else.

All duplicate entries. If every log entry is identical (same user, same minute), the map has one key mapping to a set of size 1. The answer is [1, 0, 0, ..., 0].

Each user active for exactly one minute. When no user has more than one unique minute, the answer array has a count at index 0 and zeros elsewhere. This is common in sparse log data.

Large k with few users. If k is much larger than the number of users, most of the answer array will be zeros. The algorithm still runs in O(n) time because it only touches each user once during the counting phase.

From understanding to recall

Reading through this solution once gives you the intuition, but recalling the two-phase pattern (group with sets, then count frequencies) under time pressure is a different skill. Spaced repetition helps you internalize both the "hash map of sets for deduplication" building block and the "frequency array from computed metrics" building block so they become automatic when you see similar problems. Practicing these patterns in isolation, then combining them, is what moves a solution from "I could figure it out" to "I know exactly what to do."

Related posts