01 / 本课学习路线
本课学习路线
错误分类 40 分钟 · 独立重写 90 分钟 · 安排后续复习 15 分钟
02 / 订正流程与完成条件
订正不是重做一遍:四个动作,每道错题各走一次
「再做一遍」不是修复。订正的定义是:说清第一次错在哪一类、用一个最小用例复现它、改掉它、证明改对了、再不看旧代码重写一次。
| 动作 | 做什么 | 产出 | 对应正文 |
|---|---|---|---|
| ① 分类 | 按第一次出错的原因归到六类之一 | 记录表的「首次错误类别」 | 第 03 节 |
| ② 定位并修复 | 找到导致错误的那几行代码或那条被漏读的规则,改掉 | 记录表的「一句话描述」 | 第 03、04 节 |
| ③ 最小验证 | 构造一个只触发该错误的输入,修复前失败、修复后通过 | 记录表的「反例输入」 | 第 04、05 节 |
| ④ 独立重写 | 不看旧代码从空文件重写整题,用反例与题面示例验证后提交 | 记录表的「独立修改状态」 | 第 05 节 |
完成条件:本课没有新的必做题,也不新增在线练习题。本课算完成 = 页面下方「学习完成检查」四条全部勾选:错误原因记录表填完且每行带反例、全部未通过的题独立重写并通过反例与题面示例、能说明每道题的原错误与修正、记录表已保存。未通过的题还没重写通过时,可以带着问题继续学习,但对应检查项保持未勾选。
03 / 六类错误的判定与定位
只记第一处出错:判定信号、定位步骤、修复动作
后面的错误往往是第一处的连锁,所以只记第一处。分类不靠感觉,靠信号:先看判题结果是哪一种,再用下面的问题逐个排除。
| 类型 | 判定信号 | 定位步骤 | 修复动作 | 最小用例怎么构造 |
|---|---|---|---|---|
| 读题 | 样例能过、某些用例答案错误(WA);对不可达输出、并列规则、坐标约定、截断规则的理解与题目页不一致 | 重新写题目要求清单:输出约定、并列、特殊值;逐条对照代码 | 按那一条改一处 | 构造恰好落在规则上的输入(案例 A:两个框不相交) |
| 建模 | 所有用例都错或大面积错;说不清状态是什么、一轮做什么、谁影响谁 | 写出方法一句话,用手算的小例子逐步对照程序 | 换状态定义 / 改处理顺序 | 取题面示例或比它更短的输入(案例 B:三个框排成一条链) |
| 边界 | 只有特定输入错:起点即终点、空输入、全负数、单元素 | 列出四类边界输入逐个手算 | 补上判断或特判 | 就是那个边界输入本身 |
| 复杂度 | 超时(TLE),且不是读入问题 | 估算最坏次数:每个窗口重新求和、对每个候选重数一遍 | 换成一趟扫描 / 前缀统计 / 更合适的数据结构 | 构造最大规模输入计时 |
| 语言 | 运行错误(RE)或结果对不上却找不到逻辑错 | 写 3 行小实验:整数除法、负下标、round | 换成明确的写法 | 触发该语言行为的最短输入 |
| 输出格式 | 答案错误(WA)或格式错误(PE),数字都对 | 把自己的输出与期望输出逐字节对比 | 改位数、分隔符、行数(案例 C:固定 4 位小数) | 题面示例 |
区分「读题」和「建模」:错误来自遗漏或误解明确的题目条件,归为读题;条件理解正确但算法或状态设计错误,归为建模。「错误原因」必须具体到能据此直接改代码——「粗心」不符合要求,「交集宽为负时没有截到 0,两个负数相乘成了正的交集」符合。
04 / 三个完整订正案例
失败用例 → 定位 → 修改前后对照 → 复测
三个案例来自第 50 课的 AI014 与 AI015,每个都走完整流程;你的错题按同样的格式处理。模拟考试三题的解析在交卷后的考试页,本页不重复。
案例 A · 读题类:AI014 不相交的两个框算出了正的交集
判题结果: 答案错误(WA);相交的框都对,某些用例错 失败用例: 1 1 / 0 0 4 4 / 1 6 3 8 期望 0.0000 实际 -1.8334 定位: 两个框 x 方向相交、y 方向不相交:交集高 = min(4, 8) − max(0, 6) = −2;宽 2 × 高 −2 = −4 被当成交集,并集也跟着算错 修复: 宽、高各自先和 0 取较大值再相乘(见下方前后对照) 复测: 1 1 / 0 0 4 4 / 1 6 3 8 → 0.0000 ✓ 只相接的两框 → 0.0000 ✓ 题面示例 → 与示例输出一致 ✓
案例 A 修改前(片段)
Python# AI014:交集宽、高直接相减——两个框不相交时得到负数,乘起来反而成了正的「交集」
iw = min(a[2], b[2]) - max(a[0], b[0])
ih = min(a[3], b[3]) - max(a[1], b[1])案例 A 修改后(片段)
Python# AI014:不相交(含只相接)时交集宽或高为负或 0,先截到 0 再相乘
iw = max(0.0, min(a[2], b[2]) - max(a[0], b[0]))
ih = max(0.0, min(a[3], b[3]) - max(a[1], b[1]))只改了两行;完整程序在第 50 课第 07 节展开区。修改前后各跑一次三个复测用例,修改前第一个用例失败、修改后全部通过——这才是「修复生效」。两向都不相交时两个负数相乘为正,输出可能碰巧是 0.0000,所以要用「一向相交、一向不相交」的输入验证。
案例 B · 建模类:AI015 被压掉的框继续压别人
判题结果: 答案错误(WA);两两重叠的用例能过,成链的用例少保留一个框 失败用例: 3 0.20 / 0 0 4 2 0.90 / 2 0 6 2 0.80 / 4 0 8 2 0.70 期望 0 2 实际 0 定位: 按分数处理:第 1 个框压掉第 2 个(IoU 1/3 > 0.2);轮到第 2 个框时它已被压掉,却仍去比较并压掉第 3 个(IoU 1/3);题面规定被压掉的框不再影响其他框,第 3 个框应保留 修复: 处理到已被压掉的框时直接跳过(见下方前后对照) 复测: 链式用例 → 0 2 ✓ 2 0.5 / 0 0 2 2 0.90 / 0 0 2 1 0.80 → 0 1 ✓(IoU 恰为 0.5 不压) 题面示例 → 与示例输出一致 ✓
案例 B 修改前(片段)
Python# AI015:被压掉的框只是不进保留列表,却继续参与压别人
for pos, i in enumerate(order):
if not removed[i]:
keep.append(i)
for j in order[pos + 1:]:
if not removed[j] and iou(boxes[i], boxes[j]) > thr:
removed[j] = True案例 B 修改后(片段)
Python# AI015:已被压掉的框直接跳过,不再压别人
for pos, i in enumerate(order):
if removed[i]:
continue
keep.append(i)
for j in order[pos + 1:]:
if not removed[j] and iou(boxes[i], boxes[j]) > thr:
removed[j] = True建模类错误的定位工具是逐框手推:三个框排成一条链,谁压谁按顺序写出来,第一处与题面规则不一致的就是要改的地方。完整程序在第 50 课第 07 节展开区。
案例 C · 输出格式类:AI014 用 round 打印,位数不固定
判题结果: 格式错误(PE)或答案错误(WA);数值都对 失败用例: 1 1 / 0 0 3 3 / 1 0 4 3 期望 0.5000 实际 0.5 定位: round(v, 4) 得到的是数值 0.5,转成字符串后只有一位小数;题面要求固定 4 位 修复: 用固定 4 位小数的格式化函数(见下方前后对照) 复测: 1 1 / 0 0 3 3 / 1 0 4 3 → 0.5000 ✓ 不相交的两框 → 0.0000 ✓ 题面示例 → 与示例输出一致 ✓
案例 C 修改前(片段)
Python# AI014:用 round 再转字符串——0.5 只打出 "0.5",位数不固定
lines.append(" ".join(str(round(iou(p, g), 4)) for g in gt))案例 C 修改后(片段)
Python# AI014:固定 4 位小数的格式化函数
lines.append(" ".join(fmt4(iou(p, g)) for g in gt))输出格式类错误的最小用例是题面示例本身:把自己的输出与期望输出逐字节对比。
05 / 错题登记、最小验证与独立重写
两张表:错误原因记录表与逐题登记
错误原因记录表是本课的产出,模块 8 · 结课复盘还要用;逐题登记是它的展开,每道错题一条。
错误原因记录表模板
Python# 错误原因记录表(复制到自己的笔记里逐题填写)
# 题号 | 首次错误类别(读题、建模、边界、复杂度、语言、输出格式) | 一句话描述 | 反例输入 | 独立修改状态(已完成/未完成)
# 第 1 题 | | | |
# 第 2 题 | | | |
# 第 3 题 | | | |
# 规则:只记第一处出错;反例输入要具体到能复现示例填法:第 2 题|边界|未单独处理空数组|n=0|已完成。反例输入应包含复现错误所需的完整数据。
逐题登记模板(每题一条)
Python# 错题登记(每题一条;订正完把「独立重写」改成「通过」)
# 题号:
# 来源: 模拟考试第_题 / 第_课 必做 / 第_课 进阶
# 判题结果: WA / RE / TLE / PE
# 首次错误类型: 读题 / 建模 / 边界 / 复杂度 / 语言 / 输出格式
# 触发用例: 输入=____ 期望=____ 实际=____
# 错误原因: (具体到能据此直接改代码)
# 修复动作:
# 最小验证: (至少三条:触发错误的、边界另一侧的、题面示例)
# 独立重写: 未做 / 通过 / 再错(类型=__)复制进你的错题本,每订正一项填一条;如果暂时无法准确描述错误原因,请结合失败用例和代码位置进一步检查,再回到六类错误原因重新分类。
填好的示例(案例 B)
Python# 题号: AI015
# 来源: 第 50 课 进阶
# 判题结果: WA
# 首次错误类型: 建模
# 触发用例: 输入=3 0.20 / 0 0 4 2 0.90 / 2 0 6 2 0.80 / 4 0 8 2 0.70 期望=0 2 实际=0
# 错误原因: 第 1 个框压掉第 2 个后,第 2 个框仍然去和第 3 个框比较并把它压掉;题面规定被压掉的框不再影响其他框
# 修复动作: 处理到已被压掉的框时直接 continue
# 最小验证: 上面的链式用例 → 0 2 ✓ 2 0.5 / 0 0 2 2 0.90 / 0 0 2 1 0.80 → 0 1 ✓(IoU 恰为 0.5 不压) 题面示例 → 与示例输出一致 ✓
# 独立重写: 通过「触发用例」写明期望与实际;「错误原因」写到能直接改代码;「最小验证」至少三条:触发错误的、边界另一侧的、题面示例。
独立重写的三项要求
① 不查看旧代码——若仅在旧代码上局部修改,原有的建模假设可能继续保留;② 先运行自己构造的反例,再运行样例——反例针对的正是你的首次错误类别;③ 改完对照旧代码定位差异,能够说明原错误的原因、触发输入和修正后的验证结果,本题订正才完成。
重写仍未通过怎么办:对比两次失败用例和代码位置——如果是同一个用例失败,说明错误原因没定位准,回到第 03 节重新分类;如果是新的用例失败,登记一条新的错题。两次都不过也不算失败,记录表里写明具体问题,第二场开考前重读一遍。
06 / 迁移练习与三题全通过的同学做什么
分类练习、找错练习、时间分配复盘
每题先自己做,再展开答案。
练习 1(分类):用第 50 课的规则判断以下四个失败各属于六类中的哪一类。① AI015 在 2 0.5 / 0 0 2 2 0.90 / 0 0 2 1 0.80 上只保留框 0,期望保留 0、1,程序把严格大于阈值理解成大于等于;② 第 04 节案例 B 的三个框中,程序让已被压掉的框继续压别人,输出 0 而不是 0 2;③ 卷积输出长度写成 (5-2)/2+1 后传给 range,报类型错误(TypeError);④ 案例 C 打印 0.5,而题目要求 0.5000。
展开练习 1 答案
① 读题:题目规定 IoU 严格大于阈值才抑制,两框 IoU 恰好等于 0.5,应同时保留。② 建模:已抑制的框不再参与后续抑制,循环应跳过它。③ 语言:Python 的 / 得到浮点数 2.5,range 要整数;尺寸公式应使用向下取整的整数除法 (5-2)//2+1,结果为 2。④ 输出格式:数值相同,但题目要求固定四位小数,应按案例 C 格式化。
练习 2(找错并写最小用例):一位同学的 AI015 把压框条件写成 iou > thr 以外的 iou >= thr。写出它的错误类型、一个最小用例(含期望与实际表现)和修复动作。
展开练习 2 答案
类型:读题(题面规定严格大于阈值才压)。最小用例:2 0.5 / 0 0 2 2 0.90 / 0 0 2 1 0.80——两框 IoU 恰为 0.5,正确保留两个(0 1),写成 >= 只剩 0。修复:比较改回严格大于。复测:题面示例仍通过。
练习 3(三题全通过的同学):把三道题各自的用时与 30、45、45 分钟的建议用时对照,写一句「下次哪题应该先做、为什么」;再把用时最长的一题限时 25 分钟从空文件重写一次。
展开练习 3 参考
常见的结论有两种:先做规则最清晰、读题最短的题(把有把握的分先拿到),或先做最难的题(趁精力最好)。两种都可以,但要写下依据——下一场开考前的 10 分钟通读就按这句话排顺序,交卷后再对照一次。
07 / 练习
按顺序完成本课的任务
2 项自测任务,完成情况由你自己核对
填完错误原因记录表
必做任务 1自主练习练习重点:第一场模拟考试每道未通过题的首次错误类别、一句话描述、可复现的反例;预计用时:40 分钟
完成标准:每行包含具体错误步骤和可复现输入
需要时查看提示
区分「读题」和「建模」:若错误来自遗漏或误解明确的题目条件,归为读题;若条件理解正确但算法或状态设计错误,归为建模。模板与填好的示例在第 05 节。
独立重写全部未通过的题
必做任务 2自主练习练习重点:从空文件重写;反例先行;对照旧代码定位差异;预计用时:90 分钟
完成标准:新版本通过反例与样例,并能说明原错误的原因、触发输入和修正后的验证结果
需要时查看提示
三题全部通过时可做替代任务:把三道题各自的用时与 30、45、45 分钟的建议用时对照,写一句「下次哪题应该先做」(第 06 节练习 3)。
自评状态
提交结果说明与处理方法
- WA
答案错误
独立重写后仍然答案错误:重新核对反例是否触发原错误,并检查建模、边界与实现是否仍有差异(第 05 节末段)
- PE
格式错误
若格式错误重复出现,检查清单是否覆盖该规则以及提交前是否实际执行,并把它写进第二场的开考自查
- RE
运行错误
重写版在同一处运行失败:根据错误信息和最小复现输入,重新检查原因分类与修正是否完整
- TLE
超时
先核对渐近复杂度;若不满足数据范围要求则更换方法,若满足再检查数据结构和常数开销
- AC
通过
把原错误的原因和修正方法写进错误原因记录表,再补记重写后的验证结果
08 / 学习完成检查
本课学习完成检查
完成本课需要:没有新的必做题,勾选全部学习完成检查即算完成。登录后,勾选记录会保存到账号,并更新课程总览的完成状态。