Python 1871.py
class Solution:
def findingUsersActiveMinutes(self, logs: List[List[int]], k: int) -> List[int]:
active = defaultdict(set)
for user, time in logs:
active[user].add(time)
result = [ 0 ] * k # one-based
for a in active:
minutes = len(active[a])
if minutes <= k:
result[minutes - 1] += 1 # one-based
return result
Difficulty
and has an acceptance rate of about 35% (300k+ submissions).
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The provided implementation solves the problem of counting how many users have a specific number of distinct active minutes, limited to a maximum of k different minute values. It processes a list of log entries, each containing a user identifier and a timestamp measured in minutes, and returns an array where the i-th element (zero-based) represents the number of users whose activity spans exactly i + 1 distinct minutes.
Core Logic
The algorithm proceeds in three conceptual phases: data aggregation, result preparation, and final tallying.
Data Aggregation
A defaultdict of sets is created to map each user to the collection of unique minutes at which they performed an action. The use of a set automatically eliminates duplicate timestamps for the same user.
active = defaultdict(set)
for user, time in logs:
active[user].add(time)
During this loop each (user, time) pair from the input logs is examined. The add operation on a set is constant-time on average, ensuring that the aggregation step scales linearly with the number of log entries.
Result Preparation
A list named result is allocated with a length equal to k, filled with zeros. This list will hold the final counts for each possible active-minute count from 1 to k.
result = [0] * k # one-based indexing for the final answer
Pre-allocating the list avoids repeated resizing operations that would otherwise occur if the list were built incrementally.
Final Tallying
The algorithm iterates over the aggregated user data. For each user, it computes the number of distinct minutes by taking the length of the associated set. If this count does not exceed k, the corresponding bucket in result is incremented.
for a in active:
minutes = len(active[a])
if minutes <= k:
result[minutes - 1] += 1 # adjust for zero-based index
The conditional check minutes <= k ensures that users with more than k distinct minutes are ignored, as they fall outside the required output range.
Finally, the populated result list is returned.
return result
Edge Cases Handled
The implementation gracefully manages several edge conditions without additional code.
When the input logs list is empty, the defaultdict remains empty, the subsequent loop over active does not execute, and the method returns a list of k zeros, correctly indicating that no users have any active minutes.
If a user appears multiple times with the same timestamp, the set structure automatically collapses those duplicates, so the count of distinct minutes reflects true activity diversity rather than raw log frequency.
When a user’s distinct minute count exceeds k, the conditional guard prevents any attempt to index beyond the bounds of the result list, thereby avoiding index errors and adhering to the specification that only counts up to k are required.
If k is larger than the maximum possible distinct minute count across all users, the extra slots in result simply remain zero, representing that no user achieved those higher counts.
Performance Optimizations
The code incorporates several choices that contribute to efficient execution.
Using a defaultdict(set) eliminates the need for explicit existence checks before inserting a minute value for a user. This reduces branching and keeps the inner loop tight.
Storing timestamps in a set rather than a list ensures that each insertion is amortized O(1) and that duplicate timestamps are filtered out instantly, avoiding a separate deduplication pass.
Pre-allocating the result list with a fixed size avoids dynamic resizing and repeated memory allocation that would occur if the list were grown incrementally.
The final counting loop accesses the length of each set directly, which is an O(1) operation, and updates the result array with a simple arithmetic index calculation, keeping the per-user overhead minimal.
Overall, the algorithm processes each log entry once, aggregates per-user data in constant-time structures, and produces the final counts in a single pass over the distinct users, resulting in a highly scalable solution.
ELI5 - Simplified Explanation
Imagine a big box of colorful building blocks where each block has a name on it. Some blocks have the same name because the same person picked them up at different times. The first part of this code acts like a helper who goes through all the logs and creates a separate pile for every person. Inside each person’s pile, the helper makes sure there is only one block for every unique minute that person was busy. If a person was busy at the same minute twice, the helper just keeps one block to stay organized.
Once all the piles are ready, the helper counts how many blocks are in each person’s pile. This tells everyone how many minutes that person was active. The code then prepares a set of slots lined up in a row, labeled one through k. For every person, the helper looks at the number of blocks in their pile and goes to the matching slot in the row to add a little tally mark. This keeps track of how many people were active for exactly one minute, two minutes, and so on, up to the number k. Everything ends up neatly sorted into those slots so it is easy to see the final tally of active users.
Code Quality
Complexity Analysis
As a rule of thumb, the maximum input size for one second execution time is
- factorial: up to 10 elements
- exponential: up to 20 elements
- polynomial: a few thousand elements
- loglinear: up to 100,000 elements
- linear: a few million elements
- logarithmic: a billion elements
- constant: practically unlimited
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | |||||||||
|---|---|---|---|---|---|---|---|---|---|
| author | solutions | ||||||||
| www | AlgoMonster | C++ | Python | Java | TS | ||||
| WalkCCC | C++ | Python | Java | ||||||
| leetcode.ca | C++ | JS | Python | Java | Go | Rust | TS | ||
| Progiez | C++ | Python | Java | ||||||
| github | black-shadows | C++ | |||||||
| charles-wangkai | Java | ||||||||
| everthis | JS | ||||||||
| fsq | C++ | ||||||||
| JoshCrozier | JS | ||||||||
| lkwq007 | Python | ||||||||
| suxrobGM | C# | ||||||||
| wisdompeak | C++ | ||||||||
| withaarzoo | C++ | ||||||||
| AlgoMonster | C++, Python, Java, TypeScript | ||||||||
| WalkCCC | C++, Python, Java | ||||||||
| leetcode.ca | C++, Go, Java, JavaScript, Python, Rust, TypeScript | ||||||||
| Progiez | C++, Java, Python | ||||||||
| black-shadows | C++, C++ | ||||||||
| charles-wangkai | Java | ||||||||
| everthis | JavaScript | ||||||||
| fsq | C++ | ||||||||
| JoshCrozier | JavaScript | ||||||||
| lkwq007 | Python | ||||||||
| suxrobGM | C# | ||||||||
| wisdompeak | C++ | ||||||||
| withaarzoo | C++ |
Videos
Similar Problems
- problem 1696: Jump Game VI
- problem 2297: Jump Game VIII
- problem 2559: Count Vowel Strings in Ranges
- problem 2770: Maximum Number of Jumps to Reach the Last Index
Solved On The Same Day
- problem 1184: Distance Between Bus Stops
- problem 1342: Number of Steps to Reduce a Number to Zero
- problem 1399: Count Largest Group
- problem 1496: Path Crossing
- problem 1646: Get Maximum in Generated Array
- problem 1893: Check if All the Integers in a Range Are Covered
- problem 2404: Most Frequent Even Element
- problem 2432: The Employee That Worked on the Longest Task
- problem 2451: Odd String Difference
- problem 2540: Minimum Common Value
- problem 609: Find Duplicate File in System
- problem 1169: Invalid Transactions
- problem 1711: Count Good Meals
- problem 1781: Sum of Beauty of All Substrings
- problem 1865: Finding Pairs With a Certain Sum
- problem 2013: Detect Squares
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality