The "Finding the Users Active Minutes" problem asks you to analyze user activity logs and summarize each user's unique activity minutes. Given a list of activity records, where each record contains a userID
and a minute
value, you need to find out, for each possible value of k
(from 1 to k
), how many users had exactly k
unique active minutes (UAM).
logs
, where logs[i] = [userID, minute]
. Each pair means that user userID
was active at minute minute
.
k
.
i
from 1 to k
, you must return the number of users whose count of unique active minutes is exactly i
.
answer
of length k
, where answer[i-1]
is the number of users with exactly i
unique active minutes.
Key constraints:
userID
and minute
is an integer.At first glance, it might seem like we can simply count the number of logs for each user. However, since a user can have multiple logs in the same minute, we need to count only unique minutes for each user.
The brute-force approach would be to, for each user, scan through all logs and collect their unique minutes. But this would be inefficient for large inputs.
To optimize, we can use a data structure that allows us to efficiently record and count unique minutes for each user, such as a set
for each user. Once we have the unique minutes for every user, we can count how many users had exactly 1, 2, ..., k
unique active minutes.
The shift from brute-force to optimization comes from using a hash map (dictionary) to map each user to a set of their unique minutes, and then using another array to tally the counts.
Let's break down the solution into clear steps:
userID
and the values are sets of unique minutes.
answer
of length k
initialized with zeros.
k
(inclusive), increment answer[count - 1]
by 1.
answer
array.
Why these choices?
Sample Input:
logs = [[0,5],[1,2],[0,2],[0,5],[1,3]] k = 5
Explanation:
There are 0 users with 1 unique minute, 2 users with 2 unique minutes, and 0 users for 3, 4, or 5 unique minutes.
Brute-force approach:
n
logs and u
users, this is O(u * n).u
is the number of users.The optimized approach is efficient and scales well with input size.
This problem is a great example of how to aggregate and analyze log data efficiently. By using a hash map to associate each user with a set of their unique active minutes, we avoid double-counting and make our solution both simple and fast. The final tally is a straightforward pass over the user data, producing the required summary array. The solution is elegant because it leverages the right data structures for the task and avoids unnecessary computation.
from collections import defaultdict
def findingUsersActiveMinutes(logs, k):
user_minutes = defaultdict(set)
for user, minute in logs:
user_minutes[user].add(minute)
answer = [0] * k
for minutes in user_minutes.values():
count = len(minutes)
if 1 <= count <= k:
answer[count - 1] += 1
return answer
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;
vector<int> findingUsersActiveMinutes(vector<vector<int>>& logs, int k) {
unordered_map<int, unordered_set<int>> user_minutes;
for (const auto& log : logs) {
user_minutes[log[0]].insert(log[1]);
}
vector<int> answer(k, 0);
for (const auto& pair : user_minutes) {
int count = pair.second.size();
if (count >= 1 && count <= k) {
answer[count - 1]++;
}
}
return answer;
}
import java.util.*;
class Solution {
public int[] findingUsersActiveMinutes(int[][] logs, int k) {
Map<Integer, Set<Integer>> userMinutes = new HashMap<>();
for (int[] log : logs) {
userMinutes.computeIfAbsent(log[0], x -> new HashSet<>()).add(log[1]);
}
int[] answer = new int[k];
for (Set<Integer> minutes : userMinutes.values()) {
int count = minutes.size();
if (count >= 1 && count <= k) {
answer[count - 1]++;
}
}
return answer;
}
}
var findingUsersActiveMinutes = function(logs, k) {
const userMinutes = new Map();
for (const [user, minute] of logs) {
if (!userMinutes.has(user)) userMinutes.set(user, new Set());
userMinutes.get(user).add(minute);
}
const answer = new Array(k).fill(0);
for (const minutes of userMinutes.values()) {
const count = minutes.size;
if (count >= 1 && count <= k) {
answer[count - 1]++;
}
}
return answer;
};