Software Engineer / MLE · Coding

TikTok 登录流统计:合法日期、时区与逐用户逐日计数

校验日期时间后聚合登录次数,明确格式、时区、重复事件与排序。

题目重点:校验日期时间后聚合登录次数,明确格式、时区、重复事件与排序。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练输入三元组(username,YYYY-MM-DD,HH:MM:SS),按UTC日期,不接受闰秒。
  • 每记录一次登录、不去重;任一非法记录拒绝本批。输出(username,date,count)按用户名再日期排序。实际格式与错误策略需确认。

解题路线

  1. 先检查固定格式,再用日历解析校验闰年和各月天数;正则只能查外形,不能证明2月30日合法。
  2. 校验完累加 (user,day) 计数。全批失败时不返回半成品;流式系统则可用 dead-letter 单独记录错误,必须明确不同合同。
  3. 若时间戳带时区,先转指定业务时区再提取day,不能拿UTC日期当每个用户本地日。若去重,需要稳定eventId和时间窗口,而非仅(username,time)。
  4. 排序用正式用户名比较规则;训练普通字符序,实际大小写/locale顺序另外规定。大量distinct用户日会占内存,可分区外存聚合。

手动走一遍

2024-02-29合法、2026-02-29非法;24:00:00按本文合同拒绝。同一用户同一天三条相同记录计3,因为没有去重合同;另一天单独行。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

import re
from datetime import datetime
from collections import Counter


def login_counts(records):
    """(username, UTC date YYYY-MM-DD, UTC time HH:MM:SS); no event dedup.
    Reject the entire batch on invalid date/time; output sorted triples."""
    counts = Counter()
    for user, day, time in records:
        if not isinstance(user, str) or not user:
            raise ValueError('nonempty username required')
        if not re.fullmatch(r'[0-9]{4}-[0-9]{2}-[0-9]{2}', day) or not re.fullmatch(r'[0-9]{2}:[0-9]{2}:[0-9]{2}', time):
            raise ValueError('invalid date/time format')
        datetime.fromisoformat(day + 'T' + time)  # also rejects leap seconds
        counts[user, day] += 1
    return [(user, day, count) for (user, day), count in sorted(counts.items())]

复杂度

N记录、K个用户日,解析/聚合 O(N)(字段长度有界),排序 O(K log K),空间 O(K)。无限流需窗口/分区和持久化。

易错点与追问

容易失分的边界

  • 只做正则。
  • 静默跳过错误没告知。
  • 日期按错误时区分组。
  • 无eventId就擅自合并同时间记录。

继续深挖

  • 如何支持本地日与夏令时?
  • 迟到数据和撤回事件如何修正?
✓已复制微信号!