ZipRecruiter 2026 New Grad OA 不捲演算法,但極度捲設計——一道大題分 4 個遞進 Level:CRUD、Scan & Prefix、TTL 過期清理、Backup / Restore 快照。每個 Level 單獨看都不難,但4 個 Level 必須共享一套資料結構——前面設計的偷懶會在後面付出代價。本文給出每個 Level 的最優資料結構、Python 完整解法與 ZipRecruiter codesignal 評分系統的隱藏 case 防禦。
ZipRecruiter NG OA 概覽
| 維度 | 詳情 |
|---|---|
| 平台 | CodeSignal Test |
| 時長 | 90 分鐘 |
| 題量 | 1 道大題,4 個 Level |
| 難度 | LeetCode Easy~Medium,重設計 |
| 通過線 | 80% 測試通過 |
| 評分維度 | 正確性 + Level 完成度 |
題目核心:In-memory Database
實現一個記憶體鍵值資料庫,支援嵌套結構:
db[key][field] = value
key 是頂層名稱,field 是 key 下的欄位名。所有操作要麼對 key 整體作用,要麼對 (key, field) 作用。
Level 1:基礎 CRUD
操作:
set(key, field, value):設定欄位值get(key, field):取值,不存在返回Nonedelete(key, field):刪除欄位,返回是否成功
class Database:
def __init__(self):
self.db: dict = {}
def set(self, key, field, value):
self.db.setdefault(key, {})[field] = value
def get(self, key, field):
return self.db.get(key, {}).get(field)
def delete(self, key, field):
if key in self.db and field in self.db[key]:
del self.db[key][field]
if not self.db[key]:
del self.db[key]
return True
return False
Level 1 關鍵:
- delete 返回
True/False,不要拋異常 - key 下所有 field 都被刪後,把 key 也清掉——否則 Level 2 的 scan 會返回空 key
Level 2:Scan & Prefix Filtering
操作:
scan(key):返回 key 下所有"field(value)"字串,按字典序排序scan_by_prefix(key, prefix):僅返回 field 以 prefix 開頭的
def scan(self, key):
if key not in self.db:
return []
return [f"{f}({v})" for f, v in sorted(self.db[key].items())]
def scan_by_prefix(self, key, prefix):
if key not in self.db:
return []
return [
f"{f}({v})"
for f, v in sorted(self.db[key].items())
if f.startswith(prefix)
]
Level 2 隱藏 case:
- key 不存在:返回
[](不是None,不是異常) - prefix 為空字串:返回所有欄位(等價於 scan)
- prefix 大小寫敏感
Level 3:TTL(Time-to-Live)
操作:
set_at(key, field, value, timestamp):帶時間戳的 setset_at_with_ttl(key, field, value, timestamp, ttl):設定 TTL,超過timestamp + ttl則失效get_at(key, field, timestamp):在某時間點取值,過期返回Nonedelete_at(key, field, timestamp):在某時間點刪除scan_at(key, timestamp)/scan_by_prefix_at(key, prefix, timestamp):帶時間戳的 scan
核心設計:每個欄位存 (value, start, ttl) 三元組,ttl=None 表示永久。
def _is_alive(self, entry, timestamp):
value, start, ttl = entry
if ttl is None:
return True
return timestamp < start + ttl
def set_at(self, key, field, value, timestamp):
self.db.setdefault(key, {})[field] = (value, timestamp, None)
return ""
def set_at_with_ttl(self, key, field, value, timestamp, ttl):
self.db.setdefault(key, {})[field] = (value, timestamp, ttl)
return ""
def get_at(self, key, field, timestamp):
if key not in self.db or field not in self.db[key]:
return None
entry = self.db[key][field]
if not self._is_alive(entry, timestamp):
return None
return entry[0]
def delete_at(self, key, field, timestamp):
if key not in self.db or field not in self.db[key]:
return False
entry = self.db[key][field]
if not self._is_alive(entry, timestamp):
return False
del self.db[key][field]
if not self.db[key]:
del self.db[key]
return True
def scan_at(self, key, timestamp):
if key not in self.db:
return []
alive = [
(f, e[0]) for f, e in self.db[key].items()
if self._is_alive(e, timestamp)
]
return [f"{f}({v})" for f, v in sorted(alive)]
Level 3 三個高頻扣分點:
- scan 不能清理過期欄位 —— 只過濾不刪除
- delete_at 對過期欄位返回 False —— 已過期等價於「不存在」
- TTL 是
start + ttl嚴格小於的判斷 ——timestamp < start + ttl而不是<=
Level 4:Backup / Restore
操作:
backup(timestamp):把當前資料庫狀態快照儲存restore(timestamp, target_timestamp):恢復到target_timestamp 之前最近一次 backup的狀態;恢復時所有欄位的 ttl 按 target_timestamp 到當前 timestamp 的差****重新計算剩餘 TTL
def __init__(self):
self.db: dict = {}
self.backups: list = []
def _snapshot(self, timestamp):
snap = {}
for key, fields in self.db.items():
snap_fields = {}
for f, (v, start, ttl) in fields.items():
if ttl is None:
snap_fields[f] = (v, None, None)
continue
remaining = start + ttl - timestamp
if remaining > 0:
snap_fields[f] = (v, timestamp, remaining)
if snap_fields:
snap[key] = snap_fields
return snap
def backup(self, timestamp):
self.backups.append((timestamp, self._snapshot(timestamp)))
return str(sum(len(fs) for fs in self.backups[-1][1].values()))
def restore(self, timestamp, target_timestamp):
candidate = None
for bk_ts, snap in self.backups:
if bk_ts <= target_timestamp:
candidate = (bk_ts, snap)
if candidate is None:
self.db = {}
return ""
bk_ts, snap = candidate
self.db = {}
for key, fields in snap.items():
for f, (v, start, ttl) in fields.items():
if ttl is None:
self.db.setdefault(key, {})[f] = (v, timestamp, None)
else:
self.db.setdefault(key, {})[f] = (v, timestamp, ttl)
return ""
Level 4 關鍵設計:
- snapshot 時只儲存仍存活的欄位——過期的不能 restore 回來
- restore 時所有 TTL 以 restore 時間為錨點重新計算——這是 ZipRecruiter 這一 Level 的「狠點」
- 找不到合適 backup 時,清空資料庫而非保留當前狀態
ZipRecruiter OA 通關策略
1)Level 優先級:1 → 2 → 3 → 4
每個 Level 佔總分約 25%。Level 1+2 寫到 100% = 50% 保底,足以進入 CodeSignal 的 Top 30% 分位。Level 3 是難度突變點——TTL 設計錯就 Level 3 全掛。Level 4 是 stretch goal。
2)資料結構一次到位
不要 Level 1 用 db[key][field] = value,Level 3 改成 (value, start, ttl)——會逼你重寫 Level 1+2 的所有程式碼。Level 1 就用 tuple,永久欄位用 (value, 0, None)。
3)函式返回值類型一致
CodeSignal 評分對字串 / None / boolean / "" 返回值類型敏感。題面要求返回什麼就嚴格返回什麼——get_at 返回 None,set_at 返回 "",delete_at 返回 boolean。
FAQ
ZipRecruiter OA 通過率高嗎?
整體約 40-50%。Level 1+2 完成度高的候選人通過率 70%+,Level 3 是淘汰主戰場——TTL 語義稍有偏差會扣 25% 分。
CodeSignal Test 有除錯環境嗎?
有。CodeSignal 提供 stdout 列印 + 自訂測試 case 執行。強烈建議每完成一個 Level 手動跑 3-5 個邊界 case:空 key、空 prefix、TTL 剛好過期、backup 後再 delete。
4 個 Level 都做完需要多久?
熟練 candidate 約 60-75 分鐘。前 10 分鐘規劃 → 20 分鐘 Level 1+2 → 30 分鐘 Level 3 → 15 分鐘 Level 4。Level 4 來不及的話保住 Level 3 滿分也能進 final round。
這道題的「親戚」是什麼?
CodeSignal 同款資料庫題:Snowflake、Optiver、Capital One、Roku 都有變體。前綴 + TTL 幾乎是 CodeSignal 平台的標準模板,題面只換「資料庫 → 倉庫 → 使用者系統」。
ZipRecruiter OA 之後會有什麼輪次?
OA 通過後進入 1 輪 HR Phone Screen,再到 2-3 輪 Technical Onsite(含 1 輪 Behavioral + 1-2 輪 Coding + 1 輪 System Design for senior 崗位)。從 OA 到 onsite 平均 2-4 週。
正在準備 ZipRecruiter NG OA?
oavoservice 提供 CodeSignal 記憶體資料庫題型全流程輔助:Level 拆解、TTL 設計模板、Backup / Restore 快照演算法。我們對 ZipRecruiter、Snowflake、Optiver 等 CodeSignal 系列公司的 4-Level 設計題有完整複盤,可以根據你的目標公司客製 OA 演練。
立即加入微信:Coding0201,獲取 ZipRecruiter OA 一對一輔導。
#ZipRecruiter #ZipRecruiterOA #NewGrad #CodeSignal #記憶體資料庫 #OA真題
聯絡方式
Email: [email protected]
Telegram: @OAVOProxy