🙄

100日アルゴリズム[20日目・ユーザーごとのカウント]

2025/01/28に公開

解いた問題

https://leetcode.com/problems/count-mentions-per-user/description/

解法

あまり綺麗に書けなかった。コードはパスするが、もっといい対処法がありそう。

function countMentions(numberOfUsers: number, events: string[][]): number[] {
  type UserStatus = {
    calledCount: number;
    isOnline: boolean;
    offlineTimeStamp: number;
  };

  // 初期化: 各ユーザーの状態を保持するマップを作成
  const userStatusMap = new Map<number, UserStatus>();
  for (let i = 0; i < numberOfUsers; i++) {
    userStatusMap.set(i, {
      calledCount: 0,
      isOnline: true,
      offlineTimeStamp: -1,
    });
  }

  // イベントをソートする
  const sortedEvents = [...events].sort((a, b) => {
    const timeA = Number(a[1]);
    const timeB = Number(b[1]);
    if (timeA !== timeB) {
      return timeA - timeB;
    }
    // 同じタイムスタンプの場合、OFFLINEを先に処理
    return a[0] === "OFFLINE" ? -1 : b[0] === "OFFLINE" ? 1 : 0;
  });

  // イベント処理
  for (const event of sortedEvents) {
    const [eventType, timestampStr, eventData] = event;
    const timestamp = Number(timestampStr);

    if (eventType === "OFFLINE") {
      // OFFLINEイベントの場合、指定されたユーザーをオフラインにする
      const userId = Number(eventData);
      const userStatus = userStatusMap.get(userId)!;
      userStatus.isOnline = false;
      userStatus.offlineTimeStamp = timestamp;
    } else if (eventType === "MESSAGE") {
      // MESSAGEイベントの場合、メッセージの対象ユーザーを処理
      const mentionedUsers = eventData.split(" ");
      for (const mentioned of mentionedUsers) {
        if (mentioned === "ALL") {
          // 全ユーザーを言及
          for (const [userId, userStatus] of userStatusMap.entries()) {
            userStatus.calledCount++;
          }
        } else if (mentioned === "HERE") {
          // オンラインユーザーを言及
          for (const [userId, userStatus] of userStatusMap.entries()) {
            if (
              userStatus.isOnline ||
              timestamp - userStatus.offlineTimeStamp >= 60
            ) {
              userStatus.calledCount++;
            }
          }
        } else if (mentioned.startsWith("id")) {
          // 特定のユーザーを言及
          const userIds: number[] = mentioned
            .replace("id", "")
            .split(" ")
            .map(Number);
          for (const userId of userIds) {
            const userStatus = userStatusMap.get(userId)!;
            userStatus.calledCount++;
          }
        }
      }
    }
  }

  // 結果を返す
  const result: number[] = [];
  for (let i = 0; i < numberOfUsers; i++) {
    result.push(userStatusMap.get(i)!.calledCount);
  }
  return result;
}

以下に計算量など記述しました。
https://leetcode.com/problems/count-mentions-per-user/solutions/6339359/intuitive-and-easy-to-understand-solutio-v78k/

Discussion