Medium

题目描述

给你用户在 LeetCode 上的行为日志,还有一个整数 k。日志用二维整数数组 logs 表示,其中 logs[i] = [IDi, timei] 表示 ID 为 IDi 的用户在第 timei 分钟执行了某个行为。

多个用户可以同时执行行为,单个用户也可以在同一分钟内执行多次行为。

某指定用户的 用户活跃分钟数(UAM) 定义为用户在 LeetCode 上执行行为的 不同分钟数。即使一分钟内执行多个行为,该分钟也只能按一次计算。

你需要计算一个长度为 k、下标从 1 开始 的数组 answer,对于每个 j(1 <= j <= k),answer[j] 是 UAM 等于 j 的用户数量。

请你返回上面描述的数组 answer。

示例 1:

输入:logs = [[0,5],[1,2],[0,2],[0,5],[1,3]], k = 5
输出:[0,2,0,0,0]
解释:
ID=0 的用户在第 5、2、5 分钟执行了行为。因此,该用户的 UAM 为 2(第 5 分钟只计算一次)。
ID=1 的用户在第 2、3 分钟执行了行为。因此,该用户的 UAM 为 2。
由于两个用户的 UAM 都是 2,所以 answer[2] 是 2,其余 answer[j] 的值都是 0。

示例 2:

输入:logs = [[1,1],[2,2],[2,3]], k = 4
输出:[1,1,0,0]
解释:
ID=1 的用户在第 1 分钟执行了一次行为。因此,该用户的 UAM 为 1。
ID=2 的用户在第 2、3 分钟执行了行为。因此,该用户的 UAM 为 2。
有一个用户的 UAM 是 1,一个用户的 UAM 是 2。
因此,answer[1] = 1, answer[2] = 1,其余的值都是 0。

约束条件:

  • 1 <= logs.length <= 10^4
  • 0 <= IDi <= 10^9
  • 1 <= timei <= 10^5
  • k 的范围在 [某用户的最大 UAM, 10^5] 内。

解题思路

这道题需要统计每个用户的活跃分钟数(UAM),然后计算有多少用户的UAM等于每个可能的值。

核心思路:

  1. 统计每个用户的不同分钟数:使用哈希表存储每个用户ID对应的不重复时间分钟集合
  2. 计算UAM分布:遍历所有用户,统计每个UAM值对应的用户数量

具体步骤:

  • 使用 map<int, set<int>> 结构,键为用户ID,值为该用户活跃的分钟集合
  • 遍历日志数组,将每个用户的活跃分钟加入对应集合(set自动去重)
  • 创建长度为k的结果数组,初始化为0
  • 遍历所有用户,统计每个用户的UAM(即set的大小),在结果数组对应位置+1

时间复杂度分析:

  • 构建用户活跃分钟映射:O(n log m),其中n是日志数,m是平均每用户的不同分钟数
  • 统计UAM分布:O(u),其中u是用户数
  • 总体:O(n log m + u)

这种方法简洁高效,充分利用了set的去重特性和map的快速查找能力。

代码实现

class Solution {
public:
    vector<int> findingUsersActiveMinutes(vector<vector<int>>& logs, int k) {
        unordered_map<int, unordered_set<int>> userMinutes;
        
        // 统计每个用户的不同活跃分钟
        for (auto& log : logs) {
            userMinutes[log[0]].insert(log[1]);
        }
        
        vector<int> result(k, 0);
        
        // 统计每个UAM值对应的用户数量
        for (auto& [user, minutes] : userMinutes) {
            int uam = minutes.size();
            if (uam >= 1 && uam <= k) {
                result[uam - 1]++;
            }
        }
        
        return result;
    }
};
class Solution:
    def findingUsersActiveMinutes(self, logs: List[List[int]], k: int) -> List[int]:
        user_minutes = {}
        
        # 统计每个用户的不同活跃分钟
        for user_id, time in logs:
            if user_id not in user_minutes:
                user_minutes[user_id] = set()
            user_minutes[user_id].add(time)
        
        result = [0] * k
        
        # 统计每个UAM值对应的用户数量
        for minutes_set in user_minutes.values():
            uam = len(minutes_set)
            if 1 <= uam <= k:
                result[uam - 1] += 1
        
        return result
public class Solution {
    public int[] FindingUsersActiveMinutes(int[][] logs, int k) {
        var userMinutes = new Dictionary<int, HashSet<int>>();
        
        // 统计每个用户的不同活跃分钟
        foreach (var log in logs) {
            int userId = log[0];
            int time = log[1];
            
            if (!userMinutes.ContainsKey(userId)) {
                userMinutes[userId] = new HashSet<int>();
            }
            userMinutes[userId].Add(time);
        }
        
        int[] result = new int[k];
        
        // 统计每个UAM值对应的用户数量
        foreach (var minutesSet in userMinutes.Values) {
            int uam = minutesSet.Count;
            if (uam >= 1 && uam <= k) {
                result[uam - 1]++;
            }
        }
        
        return result;
    }
}
var findingUsersActiveMinutes = function(logs, k) {
    const userMinutes = new Map();
    
    // 统计每个用户的不同活跃分钟
    for (const [userId, time] of logs) {
        if (!userMinutes.has(userId)) {
            userMinutes.set(userId, new Set());
        }
        userMinutes.get(userId).add(time);
    }
    
    const result = new Array(k).fill(0);
    
    // 统计每个UAM值对应的用户数量
    for (const minutesSet of userMinutes.values()) {
        const uam = minutesSet.size;
        if (uam >= 1 && uam <= k) {
            result[uam - 1]++;
        }
    }
    
    return result;
};

复杂度分析

复杂度类型分析
时间复杂度O(n log m),其中 n 是日志数量,m 是平均每用户的不同分钟数
空间复杂度O(u × m),其中 u 是用户数量,m 是平均每用户的不同分钟数