LeetCode 3433. Count Mentions Per User
weekly contest-434。
這題有點噁心,前 50 名甚至有 34 個中招。
反正就是一堆細節 + 轉型 + 字串處理。
要是改成設計題也不至於這麼噁心。
題目
https://leetcode.com/problems/maximum-frequency-after-subarray-operation/
解法
簡而言之:系統有提及事件 (就是 @ 某人)。
有三個用法:
- @all 所有人
- @online 所有在線的人
- @someone 指定某些人,可重複,在線或否無所謂
然後還有下線事件,讓某人在 t 下線,然後會在 t+60 秒自動上線。
沒有其他的上限方式,且保證下線事件發生時,人一定在線。
目前還算有良心。
沒良心的是,範例給的事件時間是有序的,但題目可沒保證有序。
建議一率當他沒排序過,自己排。
然後同一個時間點 t 可能有好幾個事件。
這時又有題目細節,在線狀態改變優先於提及。
若同時時間內有 @ 和 OFFLINE,則會先讓人下線,然後才開始 @。
然後 t 是字串,所以比較 t 之前要轉回整數。
所以 events 排序規則是:
- 先以 t 遞增
- 若 t 相同,則 OFFLINE 優先
可用自訂排序:
def cmp(a, b):
t1 = int(a[1])
t2 = int(b[1])
if t1 != t2:
return t1-t2
if a[0] == "OFFLINE":
return -1
return 1
events.sort(key=cmp_to_key(cmp))
lambda 比較難寫:
第二對鍵值要找到 OFFLINE 讓他變成負數;其餘保持 0。
events.sort(key=lambda x:(int(x[1]), -(x[0]=="OFFLINE")))
排完 events 之後就可以依序處理事件了。
先處理上線、再處理下線、最後才是 @。
拿一個集合維護在線的人,然後弄一個 min heap 以 (online_time, id) 的結構維護上線事件。
n 很小,直接暴力給每個人 @ 計數即可。
時間複雜度很彆扭,反正大概是 O(sort + nQ),其中 Q = len(events)。
空間複雜度 O(n)。
class Solution:
def countMentions(self, n: int, events: List[List[str]]) -> List[int]:
events.sort(key=lambda x: (int(x[1]), -(x[0] == "OFFLINE")))
ans = [0] * n
online = set(range(n))
h = [] # [time, id]
for msg, curr_time, s in events:
curr_time = int(curr_time)
# online first
while h and h[0][0] <= curr_time:
t = heappop(h)
online.add(t[1])
# OFFLINE
if msg == "OFFLINE":
id = int(s)
online.remove(id)
heappush(h, [curr_time+60, id])
continue
# MESSAGE
if s == "ALL":
for i in range(n):
ans[i] += 1
continue
if s == "HERE":
for i in online:
ans[i] += 1
continue
for x in s.split():
id = int(x[2:])
ans[id] += 1
return ans
看完大神的做法,真的是學習了。
其實具體有誰在線根本不重要。
只要知道每個人上線的時間點。
class Solution:
def countMentions(self, n: int, events: List[List[str]]) -> List[int]:
events.sort(key=lambda x: (int(x[1]), -(x[0] == "OFFLINE")))
ans = [0] * n
online = [0] * n
for msg, curr_time, s in events:
curr_time = int(curr_time)
# OFFLINE
if msg == "OFFLINE":
id = int(s)
online[id] = curr_time+60
continue
# MESSAGE
if s == "ALL":
for i in range(n):
ans[i] += 1
continue
if s == "HERE":
for i in range(n):
if online[i] <= curr_time:
ans[i] += 1
continue
for x in s.split():
id = int(x[2:])
ans[id] += 1
return ans