Created
December 12, 2025 18:32
-
-
Save tatsuyax25/106dbbf6e187c0c7ebc06558cb9c95b9 to your computer and use it in GitHub Desktop.
You are given an integer numberOfUsers representing the total number of users and an array events of size n x 3. Each events[i] can be either of the following two types: Message Event: ["MESSAGE", "timestampi", "mentions_stringi"]
This event indica
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @param {number} numberOfUsers | |
| * @param {string[][]} events | |
| * @return {number[]} | |
| */ | |
| var countMentions = function(numberOfUsers, events) { | |
| // Result: mentions per user | |
| const mentions = new Array(numberOfUsers).fill(0); | |
| // Online state and offline-until times | |
| const online = new Array(numberOfUsers).fill(true); | |
| const offlineUntil = new Array(numberOfUsers).fill(-1); | |
| // Normalize and sort: | |
| // - ensure timestamps are numbers | |
| // - sort by timestamp ascending | |
| // We'll handle same-timestamp ordering by grouping, not by sort key. | |
| const normalized = events.map(e => [e[0], Number(e[1]), e[2]]); | |
| normalized.sort((a, b) => a[1] - b[1]); | |
| // Group events by timestamp | |
| const byTime = new Map(); | |
| for (const [type, ts, arg] of normalized) { | |
| if (!byTime.has(ts)) byTime.set(ts, []); | |
| byTime.get(ts).push([type, ts, arg]); | |
| } | |
| // Helper: process auto-online at a given timestamp | |
| const applyAutoOnline = (t) => { | |
| for (let u = 0; u < numberOfUsers; u++) { | |
| if (!online[u] && offlineUntil[u] <= t) { | |
| online[u] = true; | |
| offlineUntil[u] = -1; | |
| } | |
| } | |
| }; | |
| // Iterate timestamps in ascending order | |
| const times = Array.from(byTime.keys()).sort((a, b) => a - b); | |
| for (const t of times) { | |
| const bucket = byTime.get(t); | |
| // Phase 1: auto-online before any events at time t | |
| applyAutoOnline(t); | |
| // Phase 2: apply all OFFLINE events at time t | |
| for (const [type, ts, arg] of bucket) { | |
| if (type !== "OFFLINE") continue; | |
| const id = Number(arg); | |
| if (Number.isInteger(id) && id >= 0 && id < numberOfUsers) { | |
| // User becomes offline for 60 units from ts. | |
| // If already offline, extend window if needed. | |
| online[id] = false; | |
| const until = ts + 60; | |
| offlineUntil[id] = Math.max(offlineUntil[id], until); | |
| } | |
| } | |
| // Phase 3: apply all MESSAGE events at time t | |
| for (const [type, ts, arg] of bucket) { | |
| if (type !== "MESSAGE") continue; | |
| // Split tokens by whitespace; ignore empties | |
| const tokens = String(arg).trim().split(/\s+/); | |
| for (const token of tokens) { | |
| if (token === "ALL") { | |
| // All users (online or offline) | |
| for (let u = 0; u < numberOfUsers; u++) { | |
| mentions[u] += 1; | |
| } | |
| } else if (token === "HERE") { | |
| // Only currently online users (after auto-online, after OFFLINE at t) | |
| for (let u = 0; u < numberOfUsers; u++) { | |
| if (online[u]) mentions[u] += 1; | |
| } | |
| } else if (token.startsWith("id")) { | |
| // id<number> | |
| const idStr = token.slice(2); | |
| const id = Number(idStr); | |
| if (Number.isInteger(id) && id >= 0 && id < numberOfUsers) { | |
| // Explicit mentions count even if user is offline | |
| mentions[id] += 1; | |
| } | |
| // Invalid ids are ignored | |
| } | |
| // Unrecognized tokens are ignored | |
| } | |
| } | |
| } | |
| return mentions; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment