SWE · Phone Coding

DoorDash 周内时间段编码:每 5 分钟生成一个 Slot

DoorDash Phone Coding 面经题:将 Mon 10:00 AM 至 Tue 11:00 PM 等范围转成 11000、11005… 的周内五分钟编码,明确端点与跨周边界。

题目重点:DoorDash Phone Coding 面经题:将 Mon 10:00 AM 至 Tue 11:00 PM 等范围转成 11000、11005… 的周内五分钟编码,明确端点与跨周边界。

题意与假设

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

  • 时间点变体明确周循环、start排除、end可包含、第一次恰好start+5;输出Day HH:MM AM/PM,不是日序号编码。相同端点未指定持续一周还是零时长,练习选零时长并留待核。
  • 编码题未指定终点是否包含、非 5 分钟对齐输入或跨周范围。示例采用半开 [start,end),要求两端已按 5 分钟对齐,且同一周内 start≤end;否则报错。
  • 编码格式为日序号 1–7 + 24 小时制 HHMM,总长 5 位;例如 Mon 10:00 AM 是 11000,Tue 11:00 PM 是 22300。
  • 不处理时区/夏令时转换;输入是抽象周内本地时间。若真实 API 含日期和时区,需用带时区时间戳而非纯星期编码。

解题路线

  1. cyclic_timestamps把end<start解释为下一周,从start+5以5分钟步进至≤end,再取周长模格式化。非对齐start也不向整5分钟取整;例如10:02首次10:07。无法被步长命中的end不会强加输出。
  2. 严格解析星期、12 小时制小时/分钟和 AM/PM;12 AM 转 00,12 PM 转 12,其余 PM 加 12。转成从周一 00:00 起的绝对分钟数。
  3. 检查输入顺序与 5 分钟对齐,然后从 start 到 end 每次加 5 分钟;每个绝对分钟数拆回日序号、小时、分钟,按固定宽度拼接。
  4. 不直接给字符串数字加 5,因为 11055+5 并不是 11100、午夜和星期切换更会出错;始终在分钟数上迭代。

手动走一遍

Mon 10:00 AM 至 Mon 10:15 AM,按半开约定输出 [11000,11005,11010]。Mon 11:55 PM 至 Tue 12:10 AM 输出 [12355,20000,20005];12 AM/PM 解析与跨日边界均被覆盖。第二例仅为训练扩展,题目未明确该样例。

Python 参考实现

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

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

"""Training contract for five-minute weekday/time slot codes."""

import re


DAYS = {name: index for index, name in enumerate(("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"), 1)}
TIME = re.compile(r"^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (0?[1-9]|1[0-2]):([0-5][0-9]) (AM|PM)$")


def _minute_of_week(value: str) -> int:
    match = TIME.fullmatch(value)
    if match is None:
        raise ValueError("expected 'Mon 10:00 AM' style time")
    day, hour, minute, period = match.groups()
    hour24 = int(hour) % 12 + (12 if period == "PM" else 0)
    return (DAYS[day] - 1) * 1440 + hour24 * 60 + int(minute)


def slot_codes(start: str, end: str) -> list[str]:
    """Return aligned five-minute slots in the half-open range [start,end)."""
    first, last = _minute_of_week(start), _minute_of_week(end)
    if first > last or first % 5 or last % 5:
        raise ValueError("range must be ordered and five-minute aligned")
    result: list[str] = []
    for absolute_minute in range(first, last, 5):
        day = absolute_minute // 1440 + 1
        hour, minute = divmod(absolute_minute % 1440, 60)
        result.append(f"{day}{hour:02d}{minute:02d}")
    return result


def cyclic_timestamps(start: str, end: str) -> list[str]:
    """Week cycle; exclude start, include reachable end, begin exactly start+5.
    Equal endpoints mean zero duration in this training policy, not a full week.
    """
    first,last=_minute_of_week(start),_minute_of_week(end)
    if last<first:last+=7*1440
    names=list(DAYS)
    result=[]
    for absolute in range(first+5,last+1,5):
        minute=absolute%(7*1440)
        day=names[minute//1440];hour,mm=divmod(minute%1440,60)
        result.append(f"{day} {hour%12 or 12:02d}:{mm:02d} {'AM' if hour<12 else 'PM'}")
    return result

复杂度

若输出 K 个五分钟 slot,解析 O(1),生成 O(K) 时间、O(K) 输出空间。一个完整周最多 7×24×12=2016 个 slot,可提前估算响应大小。

易错点与追问

容易失分的边界

  • 12:00 AM 是 00:00,不是 12:00;12:00 PM 是 12:00,不是 24:00。
  • 从字符串编码直接累加会在每小时末、午夜和周日边界出错;应先用绝对分钟。
  • 若时间点变体包含 end,或允许 10:02 这样未对齐起点,示例会与原题不符,必须先向面试官确认取整与端点规则。

继续深挖

  • 时间点版本Sun 11:58 PM→Mon 12:08 AM输出Mon 12:03 AM、Mon 12:08 AM;Mon 10:02→10:13只输出10:07、10:12。输出在展开的时间轴上升序,不能按weekday字符串排序。
  • 若允许 Sun 跨到下一 Mon,可将 end 加一周后迭代,再按 1–7 取模;但要定义是否允许超过一周。
  • 若用真实城市时区,夏令时使本地某些五分钟段不存在或重复,需以 UTC 时间点生成并标注时区与日期。
✓已复制微信号!