OfferForge 导师 Dr. W. — 博士毕业,前 FAANG Senior MLE。研究方向为大规模分布式机器学习系统,曾在顶级国际学术会议发表多篇论文。负责团队学术方向把控与 MLE 面试辅导。
OfferForge 导师 Dr. S. — 前大厂 Senior SDE,精通分布式系统与大规模数据处理。曾在顶级技术会议发表多篇技术报告,专注于系统可扩展性与可靠性。负责课程体系设计与 System Design 面试辅导。
OfferForge 导师 Dr. L. — 前大厂 Senior SDE,深耕分布式系统与微服务架构。在服务治理、事件驱动架构方面有丰富实战经验。负责求职策略制定与 SDE 面试辅导,已帮助多位候选人斩获 Senior 级别 Offer。
一个小时,做题时间差不多45 - 50分钟,总共四个level。一般完成三个level就稳进下一轮。老题在网上有很多,这里讨论的是一道新题。
在 Level 1,题目要求按用户汇总交易金额,例如输入 [(1, 10), (2, 5), (1, 7)],输出 {1: 17, 2: 5}。思路非常直接:使用一个 HashMap<Integer, Integer> 来记录每个用户的累计金额,遍历每条交易记录时,将对应用户的金额加到 map 中。如果用户还没有出现,就初始化为当前金额。这一level的重点是编写清晰、无错误的基础逻辑,并正确处理重复用户、空输入等边界情况,时间复杂度为 O(n)。
在 Level 2,每条交易增加了时间戳字段,比如输入 [(1, 50, 10), (1, 60, 40), (2, 30, 30), (2, 80, 100)],当 t = 100 时,需要返回过去 60 秒内交易总额超过阈值的用户(例如 [1, 2])。思路是对每个用户维护一个队列 Deque<(amount, timestamp)>,每插入一条新交易时,先移除超出时间窗口的旧记录,然后更新该用户在窗口内的总和。通过 amortized O(1) 的操作,可以实时维护每个用户的滑动窗口统计,并在任意时刻查询哪些用户超出阈值。
在 Level 3,问题升级为动态维护过去 60 秒内交易额最高的前 K 个用户。给定输入 [(1, 50, 10), (1, 60, 40), (2, 80, 30), (3, 30, 40), (2, 50, 90)],当 t = 90, K = 2 时,输出应为 [2, 1]。思路是使用 HashMap 存储每个用户的当前窗口总额,同时用一个大小为 K 的 MinHeap 来追踪 top K 用户。每次用户窗口更新时,同步调整堆结构:如果新总额超过堆顶,就插入并弹出最小值。考点是如何维护堆中元素与 map 状态一致,并保持 O(log K) 的更新效率。
在 Level 4,题目转为检测交易模式。比如输入 [(1, 10, 10), (1, 120, 20), (1, 15, 30), (2, 50, 10), (2, 150, 20)],要求找出出现 [small, large, small](<20, >100, <20 连续三笔)的用户,输出 [1]。思路是对每个用户的交易序列进行状态遍历,可以用状态机来表达三个阶段:expect small → expect large → expect small again。每读一笔交易,依据金额大小进行状态转移,如果达到终态就标记该用户为可疑。