1529 字
约 5 分钟
3
S03-A02 · 题解质量评估与对拍体系
适用读者:要保证"我发布/收藏的题解是对的"的人;要维护一个有几百张卡的题库的人。
前置:S03-A01。
覆盖旧文:—(方法论)
覆盖扩展:E-S03-022(对拍:暴力解 × 随机数据 × 边界构造)。
上一篇:S03-A01 · 题库设计与难度校准
下一篇:S04 · Java 语言核心(下一系列)。
1. 一句话结论
"题解对不对"不能靠读,要靠"用暴力解对拍":正确性 = 暴力解与优化解在大量随机与边界数据上结果一致。
对拍 = 暴力解(慢但对) × 优化解(快但可能错) × 随机/边界数据生成器
遍历 N 组输入,任一组不一致即报警
2. 对拍框架(可直接用)
2.1 三个组件
| 组件 | 写法要点 |
|---|---|
暴力解 brute |
只求正确,允许 O(n²) / O(2ⁿ) |
优化解 fast |
待验证的实现 |
数据生成 gen |
小规模(n ≤ 10)+ 随机,还要覆盖边界 |
import random
def check(brute, fast, gen, rounds=1000):
for i in range(rounds):
data = gen()
a, b = brute(data), fast(data)
if a != b:
print(f"❌ 第 {i} 组不一致\n输入: {data}\n暴力: {a}\n优化: {b}")
return False
print(f"✅ {rounds} 组数据全部一致")
return True
2.2 边界数据比随机数据更重要
| 类型 | 例子 |
|---|---|
| 最小规模 | n=0、n=1 |
| 全相同 | [1,1,1,1] |
| 全不同 | 严格递增/递减 |
| 极值 | 0、-1、Integer.MAX_VALUE、空串 |
| 结构性 | 全 0、单元素重复、括号全左/全右 |
经验值:随机数据能发现 70% 的 bug,边界数据能发现剩下 30%——而后者往往是线上事故的来源。
3. 复杂度声明规范
旧文(与大量题解)常见"O(n)"就完事。规范要求三件事:
| 声明 | 反例 | 正确写法 |
|---|---|---|
| 平均/最坏 | "哈希查找 O(1)" | "平均 O(1),最坏 O(n)" |
| 摊还 | "动态数组插入 O(1)" | "摊还 O(1),单次最坏 O(n)" |
| 约束条件 | "二分 O(log n)" | "二分 O(log n),要求数组有序" |
为什么重要:本系列 B01 已说明——"O(n) 还是 O(n²)"的争论,八成是没写清口径。
4. 重复题治理(本系列实测 4 组)
| 情况 | 例子 | 治理规则 |
|---|---|---|
| 同题两卡,一张薄(≤8 点) | #4/#5/#6/#7 | 薄卡 duplicate_ref → 指向富卡;不删原卡(保留旧 ID 可追溯) |
| 同题两卡都厚 | 无(本系列未出现) | 逐段比对,差异点合并进主讲,另一张标 duplicate_ref |
| 一题多解(不同思路) | 如 #42 单调栈 vs 双指针 | 保留在主讲文章的不同小节,不拆成两篇 |
判据:"删除会不会让某个旧链接 404?" 会 → 保留并标 duplicate_ref。
5. 空壳卡治理(本系列 41 张)
| 类型 | 数量 | 处理 |
|---|---|---|
| 有富卡可并(#4/#5/#6/#7) | 4 | duplicate_ref |
| 纯题干无答案 | 25 | 补写,标新增 E-S03-111~E-S03-126 |
| 数学空壳(A-1514/A-1520) | 2 | 已在 B09 补写(E-S03-012) |
| 笔记类无题号 | 10 | 进 gaps.md「卡外内容」清单,不入正文 |
补写规则:保留原 ID(可追溯到旧文),补写内容单独标 E——这样"旧文有这条题目"和"答案是我们新写的"两件事都能查证。
6. 质量清单(发布前逐项打勾)
| # | 检查 | 判据 |
|---|---|---|
| 1 | 代码可运行 | 复制到 IDE 能编译、能过样例 |
| 2 | 边界覆盖 | 最小规模/全相同/极值 各至少 1 组 |
| 3 | 对拍通过 | 1,000 组随机 + 边界数据与暴力解一致 |
| 4 | 复杂度声明 | 时间/空间 + 平均/最坏/摊还 + 前提条件 |
| 5 | 关键洞察 | 一句话说清"为什么这样做"(不是复述代码) |
| 6 | 易错点 | 至少列 2 个(边界、溢出、去重) |
| 7 | 旧文映射 | 能追溯到源卡 ID |
7. 一次真实对拍的产出模板
### #53 最大子数组和
- 暴力:枚举所有区间求最大和,O(n²)
- 优化:Kadane,O(n)
- 对拍:1,000 组随机(n≤20)+ 5 组边界(全负、单元素、全 0、交替正负、极值)
- 结果:全部一致
- 易错点:① 全负数时不能返回 0;② 初始化用 a[0] 而非 0
- 源卡:A-2478(原空壳,已补写 E-S03-119)
8. 五个误区
| 误区 | 真相 |
|---|---|
| "样例过了就是对的" | 样例通常不含边界 |
| "随机数据够用了" | 边界数据才能抓 30% 的隐藏 bug |
| "对拍很麻烦" | 一个 20 行的 check() 能省掉无数次返工 |
| "重复题直接删" | 会让旧链接失效;应标 duplicate_ref |
| "空壳卡删掉就行" | 会丢"这道题曾经存在"的事实;应补写并标 E |
9. 自检(架构师版)
- 对拍的三个组件是什么?为什么暴力解要"慢但对"?
- 为什么边界数据比随机数据更能发现关键 bug?
- 复杂度声明必须包含哪三样?
- 重复题为什么不能直接删?
- 空壳卡补写后为什么要保留原 ID?
10. 系列收尾
S03 到此结束(19 篇)。下一系列进入 S04 · Java 语言核心(223 张旧卡),承接本系列的集合实现与复杂度认知,讲语法、类型系统、集合源码与 I/O。
S03 的验收报告见 ../acceptance.md。
本篇属于系列《S03 · 数据结构与算法》,架构师层第 2 篇。扩展点 E-S03-022。
S03-A02 · 题解质量评估与对拍体系
https://www.clxhxhhr.top/posts/5214/ 评论
0 条
还没有评论,先写一条吧。