3433.统计用户被提及情况

题目描述

有一个聊天系统,共有 numberOfUsers 个用户,编号从 0numberOfUsers - 1。所有用户初始时都处于在线状态

系统会记录一系列事件,每个事件按发生时间顺序给出,但输入数组可能未排序。每个事件是以下两种类型之一:

1. 消息事件("MESSAGE")

格式:["MESSAGE", "timestamp", "mentions"]

  • timestamp:事件发生的时间戳(正整数)
  • mentions:一个字符串,表示此次消息中提及的用户,有三种可能:
    • "ALL":提及所有用户(无论是否在线)
    • "HERE":仅提及当前在线的用户
    • "id0 id1 id2 ...":空格分隔的用户 ID 列表(如 "id1 id0 id1"),可能包含重复或离线用户

注意:提及列表中的每个 idX 都会被单独计数(重复出现则多次计数)。

2. 离线事件("OFFLINE")

格式:["OFFLINE", "timestamp", "userId"]

  • 用户 userIdtimestamp 时刻开始离线 ,并持续 60 个单位时间
  • 用户将在 timestamp + 60 时刻自动恢复在线
  • 若用户已在离线状态,新的 OFFLINE 事件会覆盖之前的离线结束时间

重要规则

  • 多个事件可能具有相同的时间戳 。此时必须先处理所有 "OFFLINE" 事件,再处理 "MESSAGE" 事件
  • 用户是否在线,仅取决于当前时间 t 与该用户的最新离线结束时间
    • 当前时间 t >= 离线结束时间 → 在线
    • 否则 → 离线

要求

请返回一个长度为 numberOfUsers 的整数数组 result,其中 result[i] 表示用户 i 在所有消息中被提及的总次数。

java 复制代码
import java.util.*;

public class Solution {
    public int[] countMentions(int numberOfUsers, List<List<String>> events) {
        List<List<String>> list = new ArrayList<>(events);
        Collections.sort(list, (a, b) -> {
            int timeA = Integer.parseInt(a.get(1));
            int timeB = Integer.parseInt(b.get(1));
            if (timeA != timeB) {
                return Integer.compare(timeA, timeB);
            }
            String typeA = a.get(0);
            String typeB = b.get(0);
            if ("OFFLINE".equals(typeA) && "MESSAGE".equals(typeB)) return -1;
            if ("MESSAGE".equals(typeA) && "OFFLINE".equals(typeB)) return 1;
            return 0;
        });

        int[] mentions = new int[numberOfUsers];
        int[] onlineUntil = new int[numberOfUsers]; // 初始为 0,表示一开始就在线

        for (List<String> e : list) {
            String type = e.get(0);
            int t = Integer.parseInt(e.get(1));
            String data = e.get(2);

            if ("OFFLINE".equals(type)) {
                int uid = Integer.parseInt(data);
                onlineUntil[uid] = t + 60;
            } else { // MESSAGE
                if ("ALL".equals(data)) {
                    for (int i = 0; i < numberOfUsers; i++) {
                        mentions[i]++;
                    }
                } else if ("HERE".equals(data)) {
                    for (int i = 0; i < numberOfUsers; i++) {
                        if (onlineUntil[i] <= t) {
                            mentions[i]++;
                        }
                    }
                } else {
                    for (String token : data.split(" ")) {
                        if (token.startsWith("id")) {
                            int uid = Integer.parseInt(token.substring(2));
                            mentions[uid]++;
                        }
                    }
                }
            }
        }

        return mentions;
    }
}
java 复制代码
public static void main(String[] args) {
    Solution sol = new Solution();
    int n = 2;
    String[][] events = {
        {"MESSAGE", "10", "id1 id0"},
        {"OFFLINE", "11", "0"},
        {"MESSAGE", "71", "HERE"}
    };

    int[] res = sol.countMentions(n, events);
    System.out.println(Arrays.toString(res)); // 输出: [2, 2]
}
相关推荐
leobertlan4 小时前
2025年终总结
前端·后端·程序员
面向Google编程5 小时前
从零学习Kafka:数据存储
后端·kafka
易安说AI6 小时前
Claude Opus 4.6 凌晨发布,我体验了一整晚,说说真实感受。
后端
易安说AI6 小时前
Ralph Loop 让Claude无止尽干活的牛马...
前端·后端
易安说AI6 小时前
用 Claude Code 远程分析生产日志,追踪 Claude Max 账户被封原因
后端
颜酱7 小时前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法
Coder_Boy_9 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
掘金者阿豪10 小时前
关系数据库迁移的“暗礁”:金仓数据库如何规避数据完整性与一致性风险
后端
ServBay10 小时前
一个下午,一台电脑,终结你 90% 的 Symfony 重复劳动
后端·php·symfony
sino爱学习11 小时前
高性能线程池实践:Dubbo EagerThreadPool 设计与应用
java·后端