北美软件工程师面经 2026:候选人在白板前讲解系统设计与算法题

Optiver SquirrelResearch 面试题2026:多层藏取系统深度解析

💼 面试代面 / OA辅助 / VO辅助

✅ 北美科技大厂面试 · 一对一真人代面

微信: leetcode-king | Telegram: @ayinterview

📚 更多面试资源:

关于我们 – 代面服务介绍

Blog – 更多面试攻略

SEO Title:

Optiver SquirrelResearch 面试题2026:OA 难题全流程拆解与高分策略

Optiver SquirrelResearch 面试题2026 是 2026 年最新高压 OA 题。
因此,这题不能只靠模板记忆。
你必须先建清晰状态机。
这是我们学员贡献的最新面经。

此外,这题同时考实现和稳定性。
你要处理初始化、入库、出库。
与此同时,你还要处理过期和回填。
换句话说,这是一道规则工程题。

2026 面试流程深度复盘:Optiver SquirrelResearch 面试题2026

首先,线上环节会先给一段长规则。
但是,很多人会漏掉失败条件。
因此,第一步是先画失败清单。
Optiver SquirrelResearch 面试题2026 常在此处拉开差距。

其次,编码一般分三段推进。
先写 init(locations)
随后写 HideNut 的合法性校验。
最后写 RetrieveNuts 的取出策略。

此外,时间语义是核心扣分点。
timestamp + TTL 到点即过期。
因此,取出前必须先清过期。
过期删除后,nut_id 必须可复用。

与此同时,部分场次有反应力测试。
典型形式是 zap n 即时操作。
因此,手速和心态都被考察。
总而言之,Optiver SquirrelResearch 面试题2026 不只考算法。

核心题目解析

具体来说,系统可拆成三层状态。
全局层管时间和 nut_id 唯一性。
地点层管多层容量。
层结构管排序和回填。

因此,容量建议用斐波那契扩展。
三层可设为 1/2/3
四层可扩为 1/2/3/5
Optiver SquirrelResearch 面试题2026 常追问这里。

此外,规则可以归纳为以下不变量。
init(locations):按地点初始化层数与容量。
HideNut:非法地点、重复 ID、容量满都返回 False
HideNut:按“由深到浅”找首个可用层写入。
RetrieveNuts:非法地点或空地点返回空列表。
RetrieveNuts:先算可达层,再做“更重优先”。
RetrieveNuts:同重按 nut_id 字典序。
– 访问下一层条件:上一层占用率 < 50%
– 非顶层取走后:上层最轻坚果下落补位。

System Design 流程图

流程图

Python 参考实现(可直接改造成面试答案)

from dataclasses import dataclass from typing import Dict, List, Optional, Tuple import heapq @dataclass class Nut: nut_id: str weight: int expire_at: float location_id: str layer: int # 0 是最上层 class Layer: def __init__(self, cap: int) -> None: self.cap = cap self.ids = set() self.max_heap: List[Tuple[int, str]] = [] # (-weight, nut_id) self.min_heap: List[Tuple[int, str]] = [] # (weight, nut_id) def size(self) -> int: return len(self.ids) def has_space(self) -> bool: return self.size() < self.cap def occupancy(self) -> float: return self.size() / self.cap if self.cap else 1.0 def add(self, nut_id: str, weight: int) -> None: self.ids.add(nut_id) heapq.heappush(self.max_heap, (-weight, nut_id)) heapq.heappush(self.min_heap, (weight, nut_id)) def remove(self, nut_id: str) -> None: self.ids.discard(nut_id) # 惰性删除,堆内脏数据稍后清理 def _clean_max(self) -> None: while self.max_heap and self.max_heap[0][1] not in self.ids: heapq.heappop(self.max_heap) def _clean_min(self) -> None: while self.min_heap and self.min_heap[0][1] not in self.ids: heapq.heappop(self.min_heap) def peek_heaviest(self) -> Optional[str]: self._clean_max() return self.max_heap[0][1] if self.max_heap else None def pop_lightest(self) -> Optional[str]: self._clean_min() if not self.min_heap: return None _, nut_id = heapq.heappop(self.min_heap) self.ids.remove(nut_id) return nut_id class SquirrelResearch: def __init__(self) -> None: self.locations: Dict[str, List[Layer]] = {} self.nuts: Dict[str, Nut] = {} self.expiry_heap: List[Tuple[float, str]] = [] self.last_ts = float("-inf") def init(self, locations: Dict[str, int]) -> None: self.locations.clear() self.nuts.clear() self.expiry_heap.clear() self.last_ts = float("-inf") for loc_id, levels in locations.items(): caps = self._fib_caps(levels) self.locations[loc_id] = [Layer(c) for c in caps] def HideNut( self, timestamp: float, location_id: str, nut_id: str, nut_weight: int, time_to_expire: float ) -> bool: if not self._tick(timestamp): return False layers = self.locations.get(location_id) if layers is None or nut_id in self.nuts: return False target = -1 for i in range(len(layers) - 1, -1, -1): # 深到浅 if layers[i].has_space(): target = i break if target < 0: return False exp = timestamp + time_to_expire self.nuts[nut_id] = Nut(nut_id, nut_weight, exp, location_id, target) layers[target].add(nut_id, nut_weight) heapq.heappush(self.expiry_heap, (exp, nut_id)) return True def RetrieveNuts( self, timestamp: float, location_id: str, max_squirrel_capacity_in_nuts: int ) -> List[str]: if not self._tick(timestamp): return [] layers = self.locations.get(location_id) if layers is None or max_squirrel_capacity_in_nuts <= 0: return [] if sum(layer.size() for layer in layers) == 0: return [] ans: List[str] = [] while len(ans) < max_squirrel_capacity_in_nuts: reachable = self._reachable_layers(layers) pick = self._pick_best(layers, reachable) if pick is None: break nut_id, layer_idx = pick self._remove_nut(nut_id, with_backfill=True) ans.append(nut_id) return ans def _fib_caps(self, levels: int) -> List[int]: if levels <= 0: return [] caps = [1] if levels == 1: return caps caps.append(2) for _ in range(2, levels): caps.append(caps[-1] + caps[-2]) return caps def _tick(self, ts: float) -> bool: if ts <= self.last_ts: # 全局递增 return False self.last_ts = ts self._purge_expired(ts) return True def _purge_expired(self, ts: float) -> None: while self.expiry_heap and self.expiry_heap[0][0] <= ts: exp, nut_id = heapq.heappop(self.expiry_heap) nut = self.nuts.get(nut_id) if not nut or nut.expire_at != exp: continue self._remove_nut(nut_id, with_backfill=True) def _reachable_layers(self, layers: List[Layer]) -> List[int]: if not layers: return [] r = [0] for i in range(len(layers) - 1): if layers[i].occupancy() < 0.5: r.append(i + 1) else: break return r def _pick_best( self, layers: List[Layer], reachable: List[int] ) -> Optional[Tuple[str, int]]: # 跨层比较:更重优先;同重按 nut_id 字典序 best_id = None best_layer = -1 best_weight = None for idx in reachable: nid = layers[idx].peek_heaviest() if nid is None: continue nut = self.nuts[nid] if ( best_id is None or nut.weight > best_weight or (nut.weight == best_weight and nid < best_id) ): best_id = nid best_weight = nut.weight best_layer = idx return None if best_id is None else (best_id, best_layer) def _remove_nut(self, nut_id: str, with_backfill: bool) -> None: nut = self.nuts.pop(nut_id, None) if nut is None: return layers = self.locations[nut.location_id] layers[nut.layer].remove(nut_id) if with_backfill and nut.layer > 0: self._backfill(nut.location_id, nut.layer) def _backfill(self, location_id: str, hole_layer: int) -> None: # 从 hole_layer 上方逐层取最轻下落,形成连锁补位 layers = self.locations[location_id] for upper in range(hole_layer - 1, -1, -1): moved_id = layers[upper].pop_lightest() if moved_id is None: break moved_nut = self.nuts[moved_id] layers[upper + 1].add(moved_id, moved_nut.weight) moved_nut.layer = upper + 1

此外,这份实现的关键复杂度很稳。

HideNut 主要是堆操作,接近 O(log N)
RetrieveNuts 每次取出也以堆操作为主。
因此,在大 N 与大 Q 下更安全。

BQ:核心考点

  • 因此,先看你能否把长规则抽成不变量。
  • 此外,看你是否能识别全部失败路径。
  • 但是,也会看你如何解释时间和过期语义。
  • 与此同时,还会看你如何压复杂度。
  • 换句话说,代码正确只是及格线。

BQ:STAR 应对策略

  1. S:因此先说场景。规则多且易错。
  2. T:随后说任务。要做高一致性模拟器。
  3. A:此外说行动。状态机+堆+哈希+惰性删除。
  4. R:最后说结果。复杂度可控,边界全覆盖。

专家备考策略与高频考点:Optiver SquirrelResearch 面试题2026

因此,备考 Optiver SquirrelResearch 面试题2026 时,先写断言表。
把非法地点、重复 ID、容量溢出先列完。
随后再写主流程。
这样能明显降低返工率。

此外,第二步是做专项压测。
你要造过期、回填、同重 ID 冲突样例。
与此同时,专测时间戳递增约束。
Optiver SquirrelResearch 面试题2026 很爱考这三类。

但是,表达顺序同样关键。
先讲模型,再讲不变量。
然后讲复杂度与可扩展点。
面试官会更快确认你的工程能力。

具体来说,可先看 权威算法参考
如果你要实战演练,可 联系我们的专家进行一对一面试辅导


🎯 面试代面 / OA辅助 — 前大厂工程师团队帮你上岸

正在为技术面试发愁?我们的北美大厂工程师团队提供专业辅导和辅助服务:

  • OA代做 — HackerRank / CodeSignal / LeetCode 等全平台覆盖,保证通过
  • 视频代面 — Google / Meta / Amazon 等主流平台,真实面试官在线
  • 模拟面试 — 1对1真实场景还原,详细反馈与改进建议
  • 简历优化 — 北美大厂HR背景,帮你打造高通过率简历

📱 微信: leetcode-king(添加请备注”面试”,回复更快)

💬 Telegram: @ayinterview(24小时在线)

⚡ 紧急面试可加急,30分钟内安排工程师对接

🚀 需要面试辅导?立即联系我们

✅ 前大厂工程师团队 · 一对一辅导 · 真实案例 · 保密协议

微信: leetcode-king | Telegram: @ayinterview

💼 北美科技大厂面试 · 面试代面 · OA辅助 · VO辅助