LeetCode-3433. 统计用户被提及情况
题目描述
给你一个整数 numberOfUsers
表示用户总数,另有一个大小为 n x 3
的数组 events
。
每个 events[i]
都属于下述两种类型之一:
- 消息事件(Message Event):
["MESSAGE", "timestampi", "mentions_stringi"]
- 事件表示在
timestampi
时,一组用户被消息提及。 mentions_stringi
字符串包含下述标识符之一:id<number>
:其中<number>
是一个区间[0,numberOfUsers - 1]
内的整数。可以用单个空格分隔 多个 id ,并且 id 可能重复。此外,这种形式可以提及离线用户。ALL
:提及 所有 用户。HERE
:提及所有 在线 用户。
- 事件表示在
- 离线事件(Offline Event):
["OFFLINE", "timestampi", "idi"]
- 事件表示用户
idi
在timestampi
时变为离线状态 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 ,
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 在事件发生时处于 在线 状态。
思路
vector<int>flag(numberOfUsers):保存状态,在线为0,离线为1
vector<int>start(numberOfUsers):保存离线起始时间
vector<int>end(numberOfUsers):保存用户最终被提及的次数
实现
class Solution {
public:
vector<int> countMentions(int numberOfUsers, vector<vector<string>>& events) {
string temp="id";
int count=0;
int row = events.size(); //获取行数
vector<int>flag(numberOfUsers);
vector<int>start(numberOfUsers);
vector<int>end(numberOfUsers);
string::size_type idx;
sort(events.begin(), events.end(), [](const vector<string>& a, const vector<string>& b) {
// 先按时间戳排序
if (stoi(a[1]) != stoi(b[1])) {
return stoi(a[1]) < stoi(b[1]);
}
// 对于相同时间戳的事件,OFFLINE排在MESSAGE前面
return a[0] == "OFFLINE"; // "OFFLINE"返回true,"MESSAGE"返回false
});
for(int i=0;i<numberOfUsers;i++){
count=0;
vector<int>flag(numberOfUsers);
for(int j=0;j<row;j++){
if(events[j][0]=="MESSAGE"){
if(flag[i]==1){
if(stoi(events[j][1])-start[i]>=60){
flag[i]=0;
}
}
idx=events[j][2].find(temp);
if(idx!=string::npos){
if(i==0){
string input =events[j][2] ;
vector<int> numbers;
regex rgx("id(\\d+)");
smatch matches;
// 迭代匹配字符串中的所有数字
string::const_iterator searchStart(input.cbegin());
while (regex_search(searchStart, input.cend(), matches, rgx)) {
// 将匹配到的数字部分转换为整数并保存
numbers.push_back(stoi(matches[1]));
// 移动到下一个匹配的位置
searchStart = matches.suffix().first;
}
for (int num : numbers) {
end[num]++;
}
}
}
if(events[j][2]=="ALL"){
count++;
}
if(events[j][2]=="HERE"){
if(flag[i]==0){
count++;
}
}
}
if(events[j][0]=="OFFLINE"){
if(i==stoi(events[j][2])){
flag[i]=1;
start[i]=stoi(events[j][1]);
}
}
}
end[i]=end[i]+count;
}
return end;
}
};