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. 自检(架构师版)

  1. 对拍的三个组件是什么?为什么暴力解要"慢但对"?
  2. 为什么边界数据比随机数据更能发现关键 bug?
  3. 复杂度声明必须包含哪三样?
  4. 重复题为什么不能直接删?
  5. 空壳卡补写后为什么要保留原 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/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。