题目重点:设计学生报名、容量预占、退课及候补递补,处理最后一个名额的竞争。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 只有register course system题名,无功能细则。练习CourseOffering按学期区分,支持报名/退课/容量和FIFO候补;先修/时间冲突检查按提供规则。
- 选课不是Course Schedule拓扑排序本身:可修课顺序与某班名额事务是不同目标。收费/成绩管理不在基础范围。
解题路线
- Course定义目录,Offering定义学期、教师、时段与capacity;Enrollment以(studentId,offeringId)唯一,状态enrolled/waitlisted/dropped。重复报名重试返回同一结果。
- 报名事务核先修/时段资格和当前名额,原子占用或进入候补。应用先count再insert会让两学生拿同最后名额,容量不变量须与写入同一事务保护。
- 退课原子释放名额并挑候补。候补递补再次检查资格,若提供确认窗口需hold状态与到期版本,不能提前把未确认候补计成正式enrolled。
- 学生同时在不同班报名引起时间冲突时,仅锁班级容量不够;需要学生日程版本/事务或明确最终校验补偿。多对象统一锁顺序降低死锁。
- 课程取消、扩容和换时段需通知与审计,不能删除对象使历史报名悬空。只给OOD对象时说明依赖Repository的原子操作,不把进程内list当多服务事务。
手动走一遍
capacity1,A/B并发报名,仅一人enrolled,另一人候补。A退课后B进入递补状态;重复退课不会释放第二个名额。若B已报名冲突班,递补重新核资格。
规模与取舍
单班报名/退课通常索引操作O(log N),候补定位按queue索引;跳过不合格候补可能需O(W)扫描。单热门班容量是串行点,读缓存不能确认名额。
易错点与追问
容易失分的边界
- 把选课OOD答成只有前置课DAG。
- 先数人数再报名,存在竞争。
- 候补资格永远沿用第一次申请时的结果。
继续深挖
- 多人同时退课,怎样保证候补顺序和容量一致?
- 跨校区时区或冲突边界是否算相邻不重叠?
