Ramp SWE OA 面经|Recipe Manager 的重名检查和版本回滚怎么衔接

Ramp OA 面经配图

Ramp OA 的菜谱管理器把四级要求接在同一个系统上:先管理菜谱,再加入食材搜索、用户编辑,最后处理版本历史和回滚。前面用一张字典写得很顺,到了恢复旧版本时,名称索引和当前内容却对不上,这才是值得提前练的部分。

这道题对应三月的一次 SWE CodeSignal 记录。准备 Ramp OA 时,可以把它当作一个完整的小系统练习,重点检查每次修改后,所有查询是否仍然看到同一份状态。

第一题:Digital Recipe Manager 四级实现

题目描述

实现菜谱的新增、读取、修改和删除,名称检查不区分大小写。后续要求加入食材搜索与排序、用户账号及编辑操作,以及每道菜谱自己的版本历史和回滚。四级内容属于同一题的扩展。

解题思路

先把菜谱本身与查询索引分开。主记录用稳定的菜谱 ID 定位;名称索引保存规范化后的名称到 ID 的映射。名称改动时,先检查新名称是否被另一条记录占用,再一起更新主记录和索引。检查失败就保持原状态,别先删掉旧名称再返回错误。

搜索从正确性开始:扫描菜谱,检查食材条件,收集命中项,最后按接口要求排序。等用户编辑加入后,再把账号检查放进修改入口。历史记录保存独立的内容副本;回滚先取出目标版本,完成校验,再替换当前内容并重建相关索引。把修改集中在少数入口,能减少各级要求之间的相互影响。

用两道菜检查名字和历史是否串了

下面是自拟练习,不额外假定测试平台的返回值:创建 ID 为 r1、名称为 Pasta 的菜谱,再尝试创建 pasta。既然名称不区分大小写,第二次创建就应被识别为重名。展示用名称仍保留原样,查询键统一转换,两个职责分开。

接着将 r1 改成 Soup,再创建另一道名为 Pasta 的菜谱 r2。此时若尝试把 r1 恢复到最初版本,就会遇到名称冲突。练习时先约定“冲突则拒绝回滚”,验证失败后 r1 仍叫 Soup,r2 仍叫 Pasta,历史内容也保持不变。正式做题时把冲突行为接到题目指定的规则上,不要让实现顺序偷偷决定结果。

历史副本也要单独测。保存版本后,修改当前菜谱的食材列表,再读取旧版本;如果旧版本也跟着变,说明两边仍引用同一个可变对象。对包含列表或字典的内容,只复制最外层容器不够。可以保存不可变值,或者在版本边界创建独立副本。

回滚是否产生一个新版本,是另一项需要单独落地的接口规则。练习可以采用“恢复后追加版本”的约定:v3 恢复 v1 的内容后生成 v4,后续编辑继续生成 v5。不要用历史版本的编号覆盖当前序号,否则后续定位历史记录会失去清晰的含义。

Ramp OA 做题时怎样组织检查

先跑通单条菜谱的生命周期,再测试两条记录互相影响的情况。名称更新、删除、回滚都要检查主记录和名称索引;食材更新后,旧关键词搜索不到、新关键词能搜到,才说明搜索读到了最新内容。搜索结果的并列排序也要测,不能依赖字典恰好按插入顺序输出。

对 N 道菜谱、每道最多 I 个食材,扫描式搜索约为 O(NI),再加命中结果的排序开销。只有输入规模需要时,才增加食材到菜谱 ID 集合的索引。多一个索引,就多一处编辑和回滚时要维护的状态,先算清收益再加。

Ramp 的 CodeSignal 边界测试讨论里,有候选人把大量时间耗在第三阶段的返回值和状态语义上。遇到这种问题,先缩成最短操作序列:一次创建、一次修改、一次查询。这个序列比反复跑整套测试更容易说明哪一步开始出错。

FAQ

名称统一小写后,还要保留原名称吗?

要。规范化的键用于重名判断,原名称用于展示。除非题目要求,别顺便删除空格或替换标点;那会扩大“相同名称”的范围。

版本回滚为什么会影响搜索?

恢复旧版本会改动食材和名称。若搜索走独立索引,就要同步撤销当前内容的索引项,再加入恢复后的索引项。只替换主记录会留下过期结果。

练习四级题要先写完整框架吗?

先写能通过当前要求的最小实现,并保留集中修改状态的入口。提前搭复杂继承关系会吃掉编码时间,也会让新增规则更难定位。

参考来源

关于 CSINTERVIEWHELP

准备 Ramp OA 时,可以围绕具体题目安排模拟练习和复盘。无论是 OA 题型解析、OA 备考辅导、VO 模拟面试、项目表达练习还是系统设计训练,都可以结合自己的薄弱环节制定练习计划:CSINTERVIEWHELP · 服务详情