3433.统计用户被提及情况:(大)模拟

【LetMeFly】3433.统计用户被提及情况:(大)模拟

力扣题目链接:https://leetcode.cn/problems/count-mentions-per-user/

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

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

  1. 消息事件(Message Event):["MESSAGE", "timestampi", "mentions_stringi"]
    <ul>
    	<li>事件表示在&nbsp;<code>timestamp<sub>i</sub></code>&nbsp;时,一组用户被消息提及。</li>
    	<li><code>mentions_string<sub>i</sub></code>&nbsp;字符串包含下述标识符之一:
    	<ul>
    		<li><code>id&lt;number&gt;</code>:其中&nbsp;<code>&lt;number&gt;</code>&nbsp;是一个区间&nbsp;<code>[0,numberOfUsers - 1]</code>&nbsp;内的整数。可以用单个空格分隔&nbsp;<strong>多个</strong> id ,并且 id 可能重复。此外,这种形式可以提及离线用户。</li>
    		<li><code>ALL</code>:提及 <strong>所有</strong> 用户。</li>
    		<li><code>HERE</code>:提及所有 <strong>在线</strong> 用户。</li>
    	</ul>
    	</li>
    </ul>
    </li>
    <li><strong>离线事件(Offline Event):</strong><code>["OFFLINE", "timestamp<sub>i</sub>", "id<sub>i</sub>"]</code>
    <ul>
    	<li>事件表示用户&nbsp;<code>id<sub>i</sub></code>&nbsp;在&nbsp;<code>timestamp<sub>i</sub></code>&nbsp;时变为离线状态 <strong>60 个单位时间</strong>。用户会在&nbsp;<code>timestamp<sub>i</sub> + 60</code>&nbsp;时自动再次上线。</li>
    </ul>
    </li>
    

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

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

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

 

示例 1:

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

输出:[2,2]

解释:

最初,所有用户都在线。

时间戳 10 ,id1 和 id0 被提及,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 ,id1 和 id0 被提及,mentions = [1,1]

时间戳 11 ,id0 离线

时间戳 12 ,"ALL" 被提及。这种方式将会包括所有离线用户,所以 id0 和 id1 都被提及,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] 的值为 MESSAGE 或 OFFLINE 。
  • 1 <= int(events[i][1]) <= 105
  • 在任意 "MESSAGE" 事件中,以 id<number> 形式提及的用户数目介于 1 和 100 之间。
  • 0 <= <number> <= numberOfUsers - 1
  • 题目保证 OFFLINE 引用的用户 id 在事件发生时处于 在线 状态。

解题方法:模拟

最多100个人,最多100个事件,所以直接暴力模拟就好了。

创建一个答案数组,初始值全部为0,接着开始遍历事件:

  • 如果事件是OFFLINE,则什么都不做,直接continue。否则一定是消息事件:
  • 如果事件是ALL,则每人+1
  • 如果事件是HERE,则先每人+1,然后再遍历一遍事件数组,如果存在60时间内的下线时间,则此人-1
  • 否则(@指定人),被提及到的人们+1

以上。

时空复杂度分析

令$e=len(events)$,$n=numberOfUsers$:

  • 单次操作时间复杂度:下线$O(1)$、所有人$O(n)$、在线人$O(n+e)$、指定人$O(len(events[i][2]))$
  • 总空间复杂度$O(n)$

AC代码

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
'''
LastEditTime: 2025-12-12 13:42:16
'''
from typing import List

class Solution:
def countMentions(self, numberOfUsers: int, events: List[List[str]]) -> List[int]:
ans: List[int] = [0] * numberOfUsers
for action, time, who in events:
if action == "OFFLINE":
continue
if who == "ALL":
ans = [x + 1 for x in ans]
elif who == "HERE":
ans = [x + 1 for x in ans]
for a, t, w in events:
if a == "OFFLINE" and int(time) - 60 < int(t) <= int(time):
ans[int(w)] -= 1
else:
for i in (int(w[2:]) for w in who.split(" ")):
ans[i] += 1
return ans # 差点忘了return

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源


3433.统计用户被提及情况:(大)模拟
https://blog.letmefly.xyz/2025/12/12/LeetCode 3433.统计用户被提及情况/
作者
发布于
2025年12月12日
许可协议