3433.统计用户被提及情况

题目描述

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

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

1. 消息事件("MESSAGE")

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

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

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

2. 离线事件("OFFLINE")

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

  • 用户 userId 在 timestamp 时刻开始离线 ,并持续 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]
}
相关推荐
卷无止境14 分钟前
如何让AI Agent老老实实遵守公司代码规范——以Pi Agent为例
后端·python
行者-全栈开发15 分钟前
SpringBoot 生产环境踩坑实录:10个真实故障案例与教训
java·spring boot·后端
JaguarJack21 分钟前
免费可商用 PHP 管理后台 CatchAdmin V5.4.1 发布,新增 MCP 支持
后端·php·laravel·服务端
Wx-bishekaifayuan24 分钟前
springboot线上中医药养生平台管理系统36753-计算机课程设计、毕业设计
java·spring boot·后端·spring·课程设计·express·旅游
IT_陈寒27 分钟前
为什么我的Vue组件总是莫名其妙更新?
前端·人工智能·后端
Wx-bishekaifayuan28 分钟前
springboot大学生就业平台47691-计算机课程设计、毕业设计
java·spring boot·后端·elasticsearch·课程设计·express·旅游
BingoGo30 分钟前
免费可商用 PHP 管理后台 CatchAdmin V5.4.1 发布,新增 MCP 支持
后端·php
汤姆yu42 分钟前
基于springboot+vue的企业OA办公系统
java·spring boot·后端·oa办公
南归北隐1 小时前
Spring AI Alibaba Graph框架实现RAG私有知识库问答
java·后端·spring·spring ai·java rag实现
打工仔折腾 AI1 小时前
鸿蒙版ToDesk远控实测:蓝牙键鼠、双模式鼠标与跨端剪贴板怎么用
后端·python·华为·性能优化·计算机外设·harmonyos·ai agent 实战