1.6 综合练习
这一节不是"刷题"。它的目标是把第一章的五种判断动作合在一起:
- 澄清问题
- 验证正确性
- 判断复杂度
- 建立模型
- 审查工具输出
提交练习时,不只交答案,还要交你的判断过程。一个答案如果说不清为什么成立,就还不算完成。
六问法思考骨架图
在开始练习之前,先给你一张快速参考图。这张图概括了第一章最重要的思维框架——六问诊断法的完整骨架。
你可以把它作为日常工作的"清单":每次面对一个算法问题(无论是自己写还是让 AI 写),都可以按这张图的顺序检查。
六问诊断法骨架
┌─────────────────────────────────────────────────────────────────┐
│ 六问诊断法骨架图 │
│ (碰 AI 之前,先跑这张清单) │
└─────────────────────────────────────────────────────────────────┘
第一步:预测锁(写下你的初始判断,封存时间)
─────────────────────────────────────────────────────
│ 输入输出是什么? │ 规模约束是什么? │
│ 最简单解法是什么? │ 我担心的边界情况? │
─────────────────────────────────────────────────────
第一问:我真的理解问题吗?
─────────────────────────────────────────────────────
│ 产出:问题规格卡 │
├─────────────────────────────────────────────────────
│ 输入 │ 数据从哪里来?格式?范围? │
│ 输出 │ 返回什么?判断/数值/列表/安排? │
│ 规模 │ n 大概多少?峰值? │
│ 约束 │ 时间/空间/准确率要求? │
│ 例子 │ 一个正常例子 + 一个边界例子 │
─────────────────────────────────────────────────────
│ AI 角色:澄清助手(找歧义,补边界,不先写代码) │
第二问:简单算法够用吗?
─────────────────────────────────────────────────────
│ 产出:暴力基线 + 复杂度预算 │
├─────────────────────────────────────────────────────
│ 暴力思路 │ 最简单正确的办法是什么? │
│ 时间复杂度 │ O(?) 是否满足规模要求? │
│ 空间复杂度 │ 需要多少额外内存? │
│ 是否够用 │ 如果够用,可能不需要优化 │
─────────────────────────────────────────────────────
│ AI 角色:基线助手(写基线代码,估算复杂度) │
第三问:有标准解法吗?
─────────────────────────────────────────────────────
│ 产出:问题类型假设 │
├─────────────────────────────────────────────────────
│ 类型信号 │ │
│ • 有对象和关系 → 图问题 │
│ • 找最短/最快 → 最优化问题 │
│ • 安排/匹配/分配 → 资源分配问题 │
│ • 序列中找规律 → 排序/查找问题 │
│ • 判断是否出现 → 查找/去重问题 │
│ 成立条件 │ 这个假设在什么情况下成立? │
│ 可能反例 │ 什么情况会让这个假设失效? │
─────────────────────────────────────────────────────
│ AI 角色:知识助手(列标准算法,给出建模条件) │
第四问:能利用特殊结构吗?
─────────────────────────────────────────────────────
│ 产出:可利用结构清单 │
├─────────────────────────────────────────────────────
│ 常见特殊结构: │
│ • 数据几乎有序 → 可能更快排序 │
│ • 数值范围小 → 计数方法可能适用 │
│ • 图稀疏 → 邻接表更合适 │
│ • 查询多更新少 → 可预处理 │
│ • 只需近似答案 → 可能更快 │
│ • 输入持续到达 → 数据流方法 │
│ 对复杂度的影响: │
│ 每条结构 → 说明能否降低时间/空间/工程成本 │
─────────────────────────────────────────────────────
│ AI 角色:优化助手(提出利用结构的方案) │
第五问:哪种范式适合?
─────────────────────────────────────────────────────
│ 产出:范式选择 + 理由 │
├─────────────────────────────────────────────────────
│ 范式对照表: │
│ • 分治:子问题独立?合并便宜? │
│ • 局部选择:局部最优为何能推出全局最优? │
│ • 记表法:状态是什么?转移是否覆盖? │
│ • 试探回退:搜索空间?剪枝安全? │
│ • 容量分配:容量如何对应约束? │
│ • 随机化:允许什么错误?如何控制失败率? │
│ • 数据流:能保存多少状态?允许近似? │
│ 选择理由:必须回答范式对应的核心问题 │
─────────────────────────────────────────────────────
│ AI 角色:证明助手(给出范式成立条件和反例) │
第六问:还是想不出来?
─────────────────────────────────────────────────────
│ 产出:边界说明 + 下一步行动 │
├─────────────────────────────────────────────────────
│ 卡住时可以做: │
│ • 回到第一问 → 检查问题是否定义错了 │
│ • 放宽约束 → 先解决简化版本 │
│ • 搜索相似问题 → 寻找标准建模 │
│ • 请 AI/专家 → 给反例/下界/替代建模 │
│ 边界说明: │
│ 我不能解决因为... 我已排除... 我不确定... 下一步... │
─────────────────────────────────────────────────────
│ AI 角色:替代助手(提供其他方向和参考材料) │
最终产出:推理收据
─────────────────────────────────────────────────────
│ 整理成一份可追溯的判断记录 │
├─────────────────────────────────────────────────────
│ 问题规格 │ │
│ 暴力基线 │ │
│ 类型假设 │ │
│ 特殊结构 │ │
│ 范式选择 │ │
│ AI 对比 │ 我 vs AI,接受/修改/拒绝理由 │
│ 剩余风险 │ 不确定点和下一步行动 │
─────────────────────────────────────────────────────骨架图使用指南
这张图不是让你背下来,而是让你每次面对问题时按顺序检查:
- 预测锁:先写下你最初的判断,哪怕可能是错的
- 第一问:把模糊需求变成清晰规格
- 第二问:找到最简单解法,判断是否够用
- 第三问:识别问题类型,缩小算法搜索范围
- 第四问:利用数据的特殊结构,可能找到更优方案
- 第五问:选择范式时,必须回答它的核心问题
- 第六问:卡住不是失败,要明确下一步做什么
- 推理收据:整理判断过程,留下可追溯的记录
关键原则:AI 可以参与每一层,但人必须承担问题定义和最终取舍的责任。
一页速查表
如果你需要一个更精简的版本,可以用下面这张表快速回顾:
| 层次 | 核心问题 | 产出 | AI 角色 |
|---|---|---|---|
| 预测锁 | 我的初始判断是什么? | 封存的预测 | 对照对象 |
| 第一问 | 我真的理解问题吗? | 规格卡 | 澄清助手 |
| 第二问 | 简单算法够用吗? | 基线+预算 | 基线助手 |
| 第三问 | 有标准解法吗? | 类型假设 | 知识助手 |
| 第四问 | 能利用结构吗? | 结构清单 | 优化助手 |
| 第五问 | 哪种范式适合? | 范式+理由 | 证明助手 |
| 第六问 | 还是想不出来? | 边界+下一步 | 替代助手 |
| 最终 | 整理推理收据 | 可追溯记录 | 无 |
提交格式
除非题目另有说明,每道综合题建议按下面格式提交:
问题规格:
- 输入:
- 输出:
- 约束:
- 边界约定:
我的判断:
- 方案:
- 正确性理由或反例:
- 时间复杂度:
- 空间复杂度:
工具协作记录:
- 我给工具的提示:
- 工具输出摘要:
- 我接受、修改或拒绝的理由:这个格式不是为了增加文档,而是为了让你的判断能被别人检查。
基础练习
练习 1.1:任务澄清三问
把下面这个模糊任务改写成清晰规格:
帮我写一个自动分组功能。
要求回答:
- 输入是什么?至少列出 4 个字段。
- 输出是什么?是一组名单、若干小组,还是一个可解释的分组方案?
- 问题结构是什么?是在分配资源、匹配条件,还是排序优先级?
- 约束是什么?哪些条件必须满足,哪些只是尽量满足?
- 至少写出 3 个边界情况。
评分重点:是否把"自动分组"从一句话变成了可实现、可测试的规格。
练习 1.2:最小反例
某工具给出下面判断:
判断一个人能否参加所有会议:先按开始时间排序,然后只要每个会议的开始时间都大于前一个会议的结束时间,就说明没有冲突。
请回答:
- 这个思路大体在解决什么问题?
- "大于"一定正确吗?
- 如果一个会议 10:00 结束,下一个会议 10:00 开始,是否冲突?请先写出你的边界约定。
- 在你的边界约定下,给出一个最小反例,或者说明为什么没有反例。
评分重点:是否先确认规格,再评价代码或规则。
练习 1.3:复杂度类比
用生活场景解释下面三种增长方式,并各写一个代码形状:
| 增长方式 | 生活场景 | 代码形状 |
|---|---|---|
Θ(n) | ||
Θ(n²) | ||
Θ(log n) |
要求:
- 生活场景要说明
n表示什么。 - 代码形状不需要完整实现,但要能看出执行次数。
- 不能只写"一层循环/两层循环",必须解释为什么执行次数是这个量级。
进阶练习
练习 1.4:隐藏成本审查
下面代码用于去掉重复名字:
def remove_duplicates(names):
result = []
for name in names:
if name not in result:
result.append(name)
return result请回答:
- 表面上有几层循环?
- 哪一行隐藏了额外工作?
- 最坏情况下,隐藏工作形成什么求和式?
- 时间复杂度是什么?
- 如果改用"见过的名字记录表",时间和空间会怎样变化?
评分重点:是否能看见一行代码背后的真实工作量。
练习 1.5:建模卡
把下面需求写成建模卡:
班级要订 30 份午餐,预算 900 元以内,至少 5 位同学需要素食,尽量让大家满意。
必须包含:
- 输出
- 输入字段
- 硬约束
- 目标
- 规模
- 至少 3 个边界情况
然后写一段提示词,让工具只审查你的模型,不写代码。提示词必须要求工具检查:
- 歧义
- 缺失边界
- 硬约束和目标是否混淆
练习 1.6:审查工具输出
假设你让工具根据练习 1.5 写代码。工具返回了一个方案:
先选择满意度最高的套餐,尽量多订;如果预算不够,再选择下一个满意度最高的套餐。
请审查这个方案:
- 它是否一定满足素食数量要求?
- 它是否一定满足库存限制?
- 它是否可能因为先选单价高的套餐,导致后面无法凑够 30 份?
- 构造一个小例子,让这个规则失败。
- 你会如何要求工具重新审查它自己的方案?
评分重点:是否能用反例攻击一个看似合理的规则。
挑战练习
练习 1.7:第一章综合任务
选择一个你熟悉的真实任务,例如:
- 安排小组展示顺序
- 从候选活动中选择周末计划
- 为自习室安排座位
- 从商品列表中找出符合条件的结果
- 给一天的学习任务排优先级
完成以下内容:
- 写一张问题规格卡:输入、输出、约束、边界。
- 写一张建模卡:硬约束、目标、规模、表示方式。
- 给出一个最简单的基线方案。
- 分析它的时间复杂度和空间复杂度。
- 构造至少 3 个测试用例,其中至少 1 个是边界情况。
- 让工具给出一个实现或方案。
- 写一份审查记录:你接受、修改或拒绝了什么,理由是什么。
最终提交应包含一份简短结论:
我认为这个方案可以 / 不可以接受。
理由是:
1.
2.
3.
仍然不确定的是:练习 1.8:六问法完整应用
问题:给定一个有向图,判断是否存在从一个点出发能回到自己的路径(有向环)。
要求按照六问法骨架图的完整流程进行分析:
- 写预测锁
- 写问题规格卡
- 给出暴力基线和复杂度预算
- 识别问题类型(与无向图环检测有何不同?)
- 列出可利用的特殊结构
- 选择范式并给出理由
- 写出边界说明和不确定点
- 整理成推理收据
评分重点:是否完整使用了六问法,每一问都有产出。
评分标准
| 维度 | 合格表现 | 不合格表现 |
|---|---|---|
| 问题规格 | 输入、输出、约束、边界清楚 | 只有一句自然语言需求 |
| 正确性 | 能给出反例或简短理由 | 只说"看起来对" |
| 复杂度 | 能说明 n 是什么,并估算增长量级 | 只背一个 O(...) |
| 建模 | 区分硬约束和目标 | 把所有要求混成一句话 |
| 工具协作 | 能审查工具输出并说明取舍 | 直接复制工具答案 |
| 六问法 | 每一问都有产出,推理可追溯 | 只说"用了六问法"但没实际产出 |
小结
第一章真正要训练的是判断能力。
你不需要在第一章记住很多算法名字,但你需要形成一套工作习惯:
- 先澄清问题,再写代码。
- 先确认规格,再验证正确性。
- 先估复杂度,再谈性能。
- 先建模,再让工具实现。
- 接受或拒绝工具输出时,要说得出理由。
- 六问法是贯穿全章的核心框架,骨架图可以作为日常速查表。
下一章会进入数据结构。重点仍然不是"背接口",而是理解不同结构适合什么约束、会带来什么代价。
上一节:1.5 建模
下一章:第2章 数据结构