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]
}
相关推荐
爬山算法4 小时前
Netty(17)Netty如何处理大量的并发连接?
java·后端
李慕婉学姐5 小时前
Springboot面向电商的仓库管理系统05uc4267(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
用户99045017780095 小时前
ruoyi-vue2集成flowable6.7.2后端篇
后端
qq_12498707535 小时前
基于springboot框架的小型饮料销售管理系统的设计与实现(源码+论文+部署+安装)
java·spring boot·后端·spring·毕业设计
我命由我123455 小时前
Python Flask 开发:在 Flask 中返回字符串时,浏览器将其作为 HTML 解析
服务器·开发语言·后端·python·flask·html·学习方法
IT_陈寒5 小时前
JavaScript 性能优化:5个被低估的V8引擎技巧让你的代码提速50%
前端·人工智能·后端
想用offer打牌6 小时前
数据库大事务有什么危害(面试版)
数据库·后端·架构
踏浪无痕6 小时前
别再只会用 Feign!手写一个 Mini RPC 框架搞懂 Spring Cloud 底层原理
后端·面试·架构