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]
}
相关推荐
阿丰资源1 小时前
基于Spring Boot的电影城管理系统(直接运行)
java·spring boot·后端
IT_陈寒1 小时前
SpringBoot自动配置的坑差点让我加班到天亮
前端·人工智能·后端
消失的旧时光-19432 小时前
Spring Boot 工程化进阶:统一返回 + 全局异常 + AOP 通用工具包
java·spring boot·后端·aop·自定义注解
追风筝的人er3 小时前
SpringBoot+Vue3 企业考勤如何处理法定假期?节假日方案、调休补班与工作日判断链路拆解
前端·vue.js·后端
金銀銅鐵3 小时前
[git] 如何丢弃对一个文件的改动?
git·后端
橘子海全栈攻城狮4 小时前
【最新源码】养老院系统管理A013
java·spring boot·后端·web安全·微信小程序
smallyoung4 小时前
具有反思能力的 Agentic RAG 实战:用 LangChain4j 实现 CRAG 纠错检索
人工智能·后端
EthanYuan4 小时前
💡RAG实践:从云知识库迁移到PostgreSQL ,并使用PGVector实现向量存储
后端
直奔標竿4 小时前
Java开发者AI转型第二十六课!Spring AI 个人知识库实战(五)——联网搜索增强实战
java·开发语言·人工智能·spring boot·后端·spring
等风来_shy5 小时前
如何写好一个 Skill
后端