news 2026/7/11 8:08:14

力扣--3433. 统计用户被提及情况

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
力扣--3433. 统计用户被提及情况

前言:

这是力扣第3433的一道中等算法题,废话不多说,看题目和代码!


题目:

给你一个整数numberOfUsers表示用户总数,另有一个大小为n x 3的数组events

每个events[i]都属于下述两种类型之一:

  1. 消息事件(Message Event):["MESSAGE", "timestampi", "mentions_stringi"]

    • 事件表示在timestampi时,一组用户被消息提及。

    • mentions_stringi字符串包含下述标识符之一:

      • id<number>:其中<number>是一个区间[0,numberOfUsers - 1]内的整数。可以用单个空格分隔 多个 id ,并且 id 可能重复。此外,这种形式可以提及离线用户。

      • ALL:提及 所有 用户。

      • HERE:提及所有 在线 用户。

  2. 离线事件(Offline Event):["OFFLINE", "timestampi", "idi"]

    • 事件表示用户iditimestampi时变为离线状态 60 个单位时间。用户会在timestampi + 60时自动再次上线。

返回数组mentions,其中mentions[i]表示 id 为i的用户在所有MESSAGE事件中被提及的次数。

最初所有用户都处于在线状态,并且如果某个用户离线或者重新上线,其对应的状态变更将会在所有相同时间发生的消息事件之前进行处理和同步。

注意 在单条消息中,同一个用户可能会被提及多次。每次提及都需要被 分别 统计。

示例 1:

输入:numberOfUsers = 2, events = [["MESSAGE","10","id1 id0"],["OFFLINE","11","0"],["MESSAGE","71","HERE"]]

输出:[2,2]

解释:

最初,所有用户都在线。

时间戳 10 ,id1id0被提及,mentions = [1,1]

时间戳 11 ,id0离线 。

时间戳 71 ,id0再次 上线 并且"HERE"被提及,mentions = [2,2]

示例 2:

输入:numberOfUsers = 2, events = [["MESSAGE","10","id1 id0"],["OFFLINE","11","0"],["MESSAGE","12","ALL"]]

输出:[2,2]

解释:

最初,所有用户都在线。

时间戳 10 ,id1id0被提及,mentions = [1,1]

时间戳 11 ,id0离线 。

时间戳 12 ,"ALL"被提及。这种方式将会包括所有离线用户,所以id0id1都被提及,mentions = [2,2]

示例 3:

输入:numberOfUsers = 2, events = [["OFFLINE","10","0"],["MESSAGE","12","HERE"]]

输出:[0,1]

解释:

最初,所有用户都在线。

时间戳 10 ,id0离线 。

时间戳 12 ,"HERE"被提及。由于id0仍处于离线状态,其将不会被提及,mentions = [0,1]

提示:

  • 1 <= numberOfUsers <= 100

  • 1 <= events.length <= 100

  • events[i].length == 3

  • events[i][0]的值为MESSAGEOFFLINE

  • 1 <= int(events[i][1]) <= 105

  • 在任意"MESSAGE"事件中,以id<number>形式提及的用户数目介于1100之间。

  • 0 <= <number> <= numberOfUsers - 1

  • 题目保证OFFLINE引用的用户 id 在事件发生时处于 在线 状态。


题目分析:

这个题目就是一个计算用户被@的次数,简单理解

ALL:@所有人

HERE:@在线人员

所有就可以理解成:

对于 ALL ,用一个变量统计所有用户被提及的次数,看到ALL就所有人加1。

对于 HERE 消息:

1、先认为所有用户都被提及了,把如同ALL,加1。
2、此刻离线的用户不能被计入,需要把这些用户的提及次数减1。
比如一个用户在 5 时刻离线,在 65 时刻在线,那么发生在 [5,64] 中的 HERE 消息个数,就是需要减去的提及次数。

借鉴 前缀和 的思想,用 [0,64] 中的 HERE 消息个数,减去 [0,4] 中的 HERE 消息个数,即为 [5,64] 中的 HERE 消息个数。

把离线事件、上线事件、HERE 消息混在一起,按照发生时间排序。相同时间的,HERE 消息排在后面。然后遍历这些事件,同时统计 HERE 消息个数 here。离线时加上 here,在线时减去 here。这样一加一减,最终减去的就是离线时的 HERE 消息个数。


代码:

class Solution {

public int[] countMentions(int numberOfUsers, List<List<String>> events) {

int[] ans = new int[numberOfUsers];

List<int[]> es = new ArrayList<>(); // (timestamp, type, id)

int all = 0;

for (List<String> e : events) {

int curT = Integer.parseInt(e.get(1)); // 当前时间

String mention = e.get(2);

if (e.get(0).charAt(0) == 'O') { // 离线

int i = Integer.parseInt(mention);

es.add(new int[]{curT, 1, i});

es.add(new int[]{curT + 60, -1, i});

} else if (mention.charAt(0) == 'A') { // @所有人

all++;

} else if (mention.charAt(0) == 'H') { // @所有在线用户

all++;

es.add(new int[]{curT, 2, -1});

} else { // @id

for (String s : mention.split(" ")) {

int i = Integer.parseInt(s.substring(2));

ans[i]++;

}

}

}

es.sort((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);

int here = 0;

for (int[] e : es) {

int type = e[1];

if (type == 2) {

here++;

} else {

// 注意 HERE 排在后面,还没有计入发生在此刻的 HERE 消息

ans[e[2]] += type * here; // type=1 是加,-1 是减

}

}

for (int i = 0; i < numberOfUsers; i++) {

ans[i] += all;

}

return ans;

}

}


代码分析:

1、初始化

一个ans数组用于统计每个用户被提交(艾特@)的次数

一个es列表用于存events中每个事件

一个all变量统计存放被@次数(提交次数)

int[] ans = new int[numberOfUsers];

List<int[]> es = new ArrayList<>(); // (timestamp, type, id)

int all = 0;

2、逻辑实现

events = [["MESSAGE","10","id1 id0"],["OFFLINE","11","0"],["MESSAGE","71","HERE"]]

events是一个列表含列表,在列表里面是字符串

先获取每个事件的时间戳和id

id这里看题要求,有三个可能

mentions_stringi字符串包含下述标识符之一:

  • id<number>:其中<number>是一个区间[0,numberOfUsers - 1]内的整数。可以用单个空格分隔多个id ,并且 id 可能重复。此外,这种形式可以提及离线用户。
  • ALL:提及所有用户。
  • HERE:提及所有在线用户。

然后all是所有人加1,here也是先所有人加1,后面删减不符合的

同时离线和离线在上线都需要加入到数组es,为后续计算here

最后还需要注意一下案例一那种情况!

for (List<String> e : events) {

int curT = Integer.parseInt(e.get(1)); // 当前时间

String mention = e.get(2);

if (e.get(0).charAt(0) == 'O') { // 离线

int i = Integer.parseInt(mention);

es.add(new int[]{curT, 1, i});//离线。type = 1

es.add(new int[]{curT + 60, -1, i});//重新上线 type = -1

} else if (mention.charAt(0) == 'A') { // @所有人

all++;

} else if (mention.charAt(0) == 'H') { // @所有在线用户

all++;

es.add(new int[]{curT, 2, -1});//here type = 2

} else { // @id

for (String s : mention.split(" ")) {

int i = Integer.parseInt(s.substring(2));

ans[i]++;

}

}

}

3、排序

对es数组进行排序,每个列表的第一个是时间戳,按时间戳升序排序,如果时间相等,先是type = -1 即重新上线的,在type = 1 即离线 ,最后再是type = 2 即here,也是升序

es.sort((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);

4、计算here

这里就是扣除here,因为统计here个数,离线是1是先记着,一旦上线变成-1,就扣除之前统计的here

int here = 0;

for (int[] e : es) {

int type = e[1];

if (type == 2) {

here++;

} else {

// 注意 HERE 排在后面,还没有计入发生在此刻的 HERE 消息

ans[e[2]] += type * here; // type=1 是加,-1 是减

}

}

5、每个用户加上all的次数

按题目分析的,每个用户都加all

for (int i = 0; i < numberOfUsers; i++) {

ans[i] += all;

}


结语:

这道题是力扣算法,可以参考 灵神 的思路和解法!加油!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/11 6:42:27

银发旅游崛起:退休后的“第二人生”革命

今年秋天&#xff0c;朋友圈里最活跃的不是年轻人&#xff0c;而是一群“银发旅行家”。62岁的兰姐从山西阳泉出发&#xff0c;一路打卡悬空寺、平遥古城&#xff0c;还计划年底去西藏。她的朋友圈几乎每天都在更新&#xff1a;自拍、风景、姐妹合照。儿子留言让她注意安全&…

作者头像 李华
网站建设 2026/7/11 7:09:40

3步精通Eino框架:构建企业级Go语言AI应用

3步精通Eino框架&#xff1a;构建企业级Go语言AI应用 【免费下载链接】eino 项目地址: https://gitcode.com/GitHub_Trending/ei/eino 想要快速掌握Eino框架&#xff0c;在Go语言AI开发领域脱颖而出&#xff1f;本文为你揭示从零到一的完整学习路径&#xff0c;让你在3…

作者头像 李华
网站建设 2026/7/11 5:12:47

如何让文件秒变二维码?文件生成二维码技巧

想把合同、简历、课件等文件快速分享给他人&#xff0c;却嫌上传邮箱、发链接太麻烦?其实只要把文件放进二维码里&#xff0c;对方扫码就能直接查看或下载&#xff0c;省时又高效。不用复杂技术&#xff0c;跟着下面的步骤操作&#xff0c;一分钟就能实现文件生成二维码&#…

作者头像 李华
网站建设 2026/7/7 11:24:12

如何实现本地图片转为二维码?本地图片生成二维码全攻略

想把合同、简历、课件等文件快速分享给他人&#xff0c;却嫌上传邮箱、发链接太麻烦?其实只要把文件放进二维码里&#xff0c;对方扫码就能直接查看或下载&#xff0c;省时又高效。不用复杂技术&#xff0c;跟着下面的步骤操作&#xff0c;一分钟就能实现文件生成二维码&#…

作者头像 李华
网站建设 2026/7/9 11:48:50

如何创作你的专属表情包?GIF动图制作全攻略

在数字社交时代&#xff0c;GIF动图已成为表达情感、分享趣味的通用语言。一张生动的GIF图&#xff0c;往往比文字更有表现力&#xff0c;比静态图片更具感染力。无论你想制作有趣的表情包、记录精彩瞬间&#xff0c;还是为内容增添动态元素&#xff0c;掌握GIF动图制作技巧都能…

作者头像 李华
网站建设 2026/7/11 0:21:30

探索数字经济前沿:2025国际期刊/国际会议

Modern Management Science & Engineering (现代管理科学与工程) 是一本由 Scholink 出版的国际性、审稿人、双盲、同行评审、开放获取期刊。MMSE的使命是为世界各地的专家和学者提供一个高水平的平台&#xff0c;分享他们最新的管理理念&#xff0c;促进学科的繁荣。期刊名…

作者头像 李华