【LetMeFly】3433.统计用户被提及情况:(大)模拟
力扣题目链接:https://leetcode.cn/problems/count-mentions-per-user/
给你一个整数numberOfUsers表示用户总数,另有一个大小为n x 3的数组events。
每个events[i]都属于下述两种类型之一:
- 消息事件(Message Event):
["MESSAGE", "timestampi", "mentions_stringi"]<ul> <li>事件表示在 <code>timestamp<sub>i</sub></code> 时,一组用户被消息提及。</li> <li><code>mentions_string<sub>i</sub></code> 字符串包含下述标识符之一: <ul> <li><code>id<number></code>:其中 <code><number></code> 是一个区间 <code>[0,numberOfUsers - 1]</code> 内的整数。可以用单个空格分隔 <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>事件表示用户 <code>id<sub>i</sub></code> 在 <code>timestamp<sub>i</sub></code> 时变为离线状态 <strong>60 个单位时间</strong>。用户会在 <code>timestamp<sub>i</sub> + 60</code> 时自动再次上线。</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 <= 1001 <= events.length <= 100events[i].length == 3events[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 = l e n ( e v e n t s ) e=len(events)e=len(events),n = n u m b e r O f U s e r s n=numberOfUsersn=numberOfUsers:
- 单次操作时间复杂度:下线O ( 1 ) O(1)O(1)、所有人O ( n ) O(n)O(n)、在线人O ( n + e ) O(n+e)O(n+e)、指定人O ( l e n ( e v e n t s [ i ] [ 2 ] ) ) O(len(events[i][2]))O(len(events[i][2]))
- 总空间复杂度O ( n ) O(n)O(n)
AC代码
Python
''' LastEditTime: 2025-12-12 13:42:16 '''fromtypingimportListclassSolution:defcountMentions(self,numberOfUsers:int,events:List[List[str]])->List[int]:ans:List[int]=[0]*numberOfUsersforaction,time,whoinevents:ifaction=="OFFLINE":continueifwho=="ALL":ans=[x+1forxinans]elifwho=="HERE":ans=[x+1forxinans]fora,t,winevents:ifa=="OFFLINE"andint(time)-60<int(t)<=int(time):ans[int(w)]-=1else:foriin(int(w[2:])forwinwho.split(" ")):ans[i]+=1returnans# 差点忘了return同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
千篇源码题解已开源