← 返回部落格列表 ZipRecruiter 2026 NG OA 真題:記憶體資料庫 4 個 Level 全解析|TTL + Backup/Restore
ZipRecruiter

ZipRecruiter 2026 NG OA 真題:記憶體資料庫 4 個 Level 全解析|TTL + Backup/Restore

2026-05-14

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

操作

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 關鍵

Level 2:Scan & Prefix Filtering

操作

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

Level 3:TTL(Time-to-Live)

操作

核心設計:每個欄位存 (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 三個高頻扣分點

  1. scan 不能清理過期欄位 —— 只過濾不刪除
  2. delete_at 對過期欄位返回 False —— 已過期等價於「不存在」
  3. TTL 是 start + ttl 嚴格小於的判斷 —— timestamp < start + ttl 而不是 <=

Level 4:Backup / Restore

操作

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 關鍵設計

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 返回 Noneset_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