上週剛刷完 Ramp 的 OA,這次是 CodeSignal 平臺 的 90 分鐘 OOD 版本,總共 4 個 Level,必須透過當前關卡所有測試用例才能解鎖下一關。我全程用 Python 寫完,40 多分鐘就 AC 了,下面把真實題目和解題思路分享給大家。

CodeSignal 平臺規則
做之前要搞清楚你拿到的是哪種 OA:
90 分鐘版本(OOD 版):四道題是同一個系統設計,關卡遞進,必須透過當前關卡所有測試才能解鎖下一題。建議用 Python,程式碼量小,後續 VO 也不會問你用了什麼語言。
70 分鐘版本(General 版):四道獨立演算法題,題庫固定,來來回回就那 100 來題,基本都是原題,可以提前刷。
Ramp 走的是 90 分鐘 OOD 版本。
題目背景
實現一個記憶體版雲端儲存系統,把檔案對映到對應的後設資料(名稱、大小等)。不需要操作真實檔案系統,全部存記憶體裡。
四個關卡遞進,透過當前關才能看到下一關的題目。
Level 1:基礎檔案操作
最基礎的增刪查,把介面實現清楚就行。
介面:
add_file(name, size)→ 檔案已存在返回 False,否則新增成功返回 Trueget_file_size(name)→ 檔案存在返回大小,不存在返回 Nonedelete_file(name)→ 刪除成功返回檔案大小,不存在返回 None
實現:
class CloudStorage:
def __init__(self):
self.files = {} # name -> size
def add_file(self, name: str, size: int) -> bool:
if name in self.files:
return False
self.files[name] = size
return True
def get_file_size(self, name: str):
return self.files.get(name, None)
def delete_file(self, name: str):
if name not in self.files:
return None
size = self.files.pop(name)
return size
這關沒有坑,雜湊表直接搞定,5 分鐘以內寫完。
Level 2:Top N 最大檔案
按字首篩選檔案,返回最大的 N 個。
介面:
get_n_largest(prefix, n)→ 返回以 prefix 開頭的最大 N 個檔案,格式為["/path/file(size)", ...]
排序規則:
- 先按大小降序
- 大小相同按檔名字典序升序
實現:
def get_n_largest(self, prefix: str, n: int) -> list:
matched = [
(name, size)
for name, size in self.files.items()
if name.startswith(prefix)
]
matched.sort(key=lambda x: (-x[1], x[0]))
return [f"{name}({size})" for name, size in matched[:n]]
踩坑點:
- 排序是雙條件,size 降序 + name 升序,lambda 裡 size 要取負
- 檔案數量不足 N 個時直接返回所有符合的,不報錯
- 沒有符合條件的檔案返回空列表
[],不是 None
Level 3:使用者容量與合併
這關加入了使用者概念,每個使用者有儲存上限,同時支援兩個使用者的儲存合併。
新增介面:
add_user(user_id, capacity)→ 註冊使用者並設定容量上限,使用者已存在返回 Falseadd_file_by(user_id, name, size)→ 為指定使用者新增檔案,超出容量或檔案已存在返回 Falsemerge_user(user_id_1, user_id_2)→ 將 user_id_2 的檔案合併到 user_id_1,合併後刪除 user_id_2
實現:
def add_user(self, user_id: str, capacity: int) -> bool:
if user_id in self.users:
return False
self.users[user_id] = {
"capacity": capacity,
"used": 0,
"files": {}
}
return True
def add_file_by(self, user_id: str, name: str, size: int) -> bool:
if user_id not in self.users:
return False
user = self.users[user_id]
if name in user["files"]:
return False
if user["used"] + size > user["capacity"]:
return False
user["files"][name] = size
user["used"] += size
self.files[name] = size # 同步到全域性
return True
def merge_user(self, user_id_1: str, user_id_2: str) -> bool:
if user_id_1 not in self.users or user_id_2 not in self.users:
return False
u1 = self.users[user_id_1]
u2 = self.users[user_id_2]
for name, size in u2["files"].items():
# 檔名衝突時 user2 的檔案直接丟棄
if name not in u1["files"]:
u1["files"][name] = size
u1["used"] += size
# 合併容量
u1["capacity"] += u2["capacity"]
# 刪除 user2
del self.users[user_id_2]
return True
踩坑點:
- 合併時檔名衝突的處理:user_2 的檔案直接丟棄,不覆蓋 user_1
- 合併後 user_2 的容量也要併入 user_1
- 容量計算用 used 欄位維護,別每次都遍歷檔案重新算
- 全域性 files 字典和使用者 files 要保持同步
Level 4:備份與恢復
這關加入了備份機制,支援對使用者儲存做快照,並在需要時恢復到指定備份狀態。
新增介面:
backup_user(user_id, timestamp)→ 對使用者當前狀態做快照,記錄時間戳restore_user(user_id, timestamp)→ 將使用者恢復到指定時間戳的快照狀態,時間戳不存在返回 False
實現:
import copy
def backup_user(self, user_id: str, timestamp: int) -> bool:
if user_id not in self.users:
return False
if user_id not in self.backups:
self.backups[user_id] = {}
# 深複製當前使用者狀態
self.backups[user_id][timestamp] = copy.deepcopy(self.users[user_id])
return True
def restore_user(self, user_id: str, timestamp: int) -> bool:
if user_id not in self.backups:
return False
if timestamp not in self.backups[user_id]:
return False
# 恢復前先從全域性 files 裡刪掉該使用者的檔案
current_files = self.users[user_id]["files"]
for name in current_files:
if name in self.files:
del self.files[name]
# 恢復快照
self.users[user_id] = copy.deepcopy(self.backups[user_id][timestamp])
# 同步全域性 files
for name, size in self.users[user_id]["files"].items():
self.files[name] = size
return True
踩坑點:
恢復後不影響其他使用者的檔案,全域性 files 只更新這個使用者相關的部分
備份時一定要用 deepcopy,淺複製的話後續修改會影響快照
恢復時要先把該使用者在全域性 files 裡的檔案清掉,再把備份裡的檔案重新寫進去
同一個時間戳可能會被覆蓋,直接覆蓋就行,不用報錯
上岸前最後一關,別靠運氣
VO 當天最怕的不是難題,是遇到沒想到的追問然後大腦一片空白。這次 Ramp 面試我找了 ProgramHelp 團隊做實時助攻。面試進行中他們全程線上,遇到卡的地方直接給我提示思路,節奏完全沒斷。不是 AI 生成的模板,是北美 CS 專家真人在旁邊幫你想,知道面試官問這句話背後想聽什麼。AI 給你一堆答案,但不知道你當下的語境;真人能跟著你的節奏走,缺哪補哪。
OA 代寫、簡歷包裝、VO 助攻都有。