面经 | SWE Intern OA | 🔥🔥🔥 | Optiver
2026(9月) Software Engineer Intern 2027 @ Optiver US | OA | 😵 Hard | Pending
OA 是 90min coding + Zap-N。coding 只有一道,但是题面很长。
OA — market data processor
题目要求
做一个简化的 market data processor。交易所会不断发 message:ADD、UPDATE、DELETE、SNAPSHOT。
每条 message 都有 symbol、price、size 和 sequence number,需要维护每个 symbol 当前最新的 bid / ask 状态。
基础部分不难。收到 ADD / UPDATE 就更新,DELETE 删掉对应 level。
Sequence number
真正麻烦的是 sequence number。
如果当前已经处理到 seq=105,下一条直接来了 107,不能直接 apply。要先把 107 暂存起来,等 106 到了以后再按照顺序处理。
如果缺失的 message 一直没来,会收到一个 SNAPSHOT。snapshot 代表某个 sequence point 的完整状态,需要用它重新恢复 book,然后再看之前 buffer 里的 message 哪些还能继续 apply。
最后的数据结构
MarketDataProcessor
symbol -> OrderBook
lastSequence
pendingMessages
OrderBook
bid / ask
process(message)
apply(message)
applySnapshot(snapshot)
后面加的规则
- duplicate message:同一个 sequence 可能重复收到,不能执行两遍。
- stale message:如果已经通过 snapshot 恢复到 seq=200,后面才收到 198,直接忽略。
- symbol 独立:AAPL 卡在 seq=50,不应该把 MSFT 的 message 也一起 block。
sequence 做成 global 还是 per-symbol 要看清题目。我前面理解错了一次,改了一部分结构。
Best bid / best ask
有一个 follow-up 是返回当前 best bid / best ask。
如果直接用 unordered_map 存 price level,查 best price 会比较麻烦。我改成用有序结构维护 price:bid 取最高,ask 取最低。DELETE 一个 price level 以后,如果它刚好是 best,需要自动更新。
Corner case
- UPDATE 一个不存在的 level
- DELETE 已经被删掉的 level
- snapshot 和 buffered update 重叠
- 连续缺多个 sequence
- duplicate snapshot
hidden case 主要挂在 snapshot + buffer 这块。前面的正常 message 都能过,最后剩了几个 testcase 没清完。
时间
90 分钟时间非常紧。不是算法本身多难,主要是先读很长的 requirement,再决定 state 怎么存,写到一半还会发现前面的 abstraction 不够用。如果一开始所有逻辑都写在 process() 里面,后面加 snapshot 基本会炸。
Zap-N
Zap-N 在 coding 后面。几个 reaction / attention game。有的是看到特定 pattern 按键,有的是短时间记住位置或者顺序。规则不复杂,但是速度会越来越快。没有什么准备空间,直接做就行。
coding 比 Zap-N 难很多。
Optiver 这类 OA 和普通刷 LC 的感觉差挺多。更像 event processing、state management、OOD 加大量 edge case,真正容易丢分的是 sequence、recovery 和状态一致性。