上周刚刷完 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 助攻都有。