跳转至

第1章 课程与审题:先把题读对,再谈优化

旧版讲义 · 校订增强 · 专题阅读 · 保留代码与校订注 · 与版本锁一致

第1章 课程与审题:先把题读对,再谈优化

这一章不教具体算法,而是建立一条稳定答题管线:圈出限制 → 确定目标 → 先保证正确 → 再用未利用条件优化 → 核对复杂度和边界。

回源 · PDF 第 1 页 · b_1_12;PDF 第 2 页 · b_2_0

1.1 算法题的得分策略

考场上为什么要“先写对,再写优”?

算法大题同时考思路、代码和复杂度,最危险的做法是长时间死磕最优解,最后连可检查的正确解都没有。

稳定顺序: 1. 先写出一个边界完整、能得到正确结果的方法。 2. 再问“题目的哪个条件还没用?我是否做了超出目标的额外工作?” 3. 找到优化后,重新检查正确性、最坏情况和额外空间。

⚠️ 讲义中的具体分值和时间只是旧版备考建议,不当作 2027 考纲或评分细则。

回源 · PDF 第 1 页 · b_1_3;PDF 第 1 页 · b_1_4;PDF 第 1 页 · b_1_5

不看视频时,这套讲义怎么用?

按“卡片预习 → 独立写题 → 对照原页 → 记录卡住的模块 → 再做一遍”使用。

  • 第一遍只掌握各章的通用方法,不背大量题解。
  • 第二遍遮住答案,至少独立写出“设计思想 + 核心代码 + 复杂度”。
  • 复盘时不只记“这题不会”,而要定位是流程不会拆,还是某个模板代码不会写。

这样无需下载或依赖录播,讲义、题目和回源页已经足够形成闭环。

回源 · PDF 第 1 页 · b_1_6;PDF 第 1 页 · b_1_7;PDF 第 1 页 · b_1_10

1.2 审题四层扫描

算法题先扫哪四层信息?

第 1 层:输出目标 - 要返回下标、数值、布尔值,还是原地修改结构? - 只要一个解,还是全部解?允许任意合法结果,还是要特定顺序?

第 2 层:复杂度目标 - “时间上尽可能高效”:先压时间,可使用合理辅助空间。 - “时间、空间都尽可能高效”:需同时说明两者的权衡。 - “空间复杂度为 \(O(1)\)”:不能开随 \(n\) 增长的数组、散列表或结点集合。

第 3 层:数据性质 - 有序 → 折半、双指针、归并。 - 取值范围小 → 计数数组或散列。 - 元素不同、全为正数、树为 BST 等 → 可删除不必要分支。

第 4 层:不可破坏的约束 - 原数组不得改变、稳定性、递归/非递归、带头结点、无向/有向、允许重复等。

💡 最后把题目压缩成一句:在什么约束下,对什么对象,求什么结果,优化哪个指标。

回源 · PDF 第 2 页 · b_2_5;PDF 第 2 页 · b_2_7;PDF 第 3 页 · b_3_13;PDF 第 3 页 · b_3_16

为什么括号、下标范围和函数原型要单独圈出?

这些位置常隐藏能否排序、能否改动原数组、是否允许辅助结构等决定性条件。

例如讲义引用的 2025 年题中,\(0\le i\le j\le n-1\) 与 res[i] 的含义共同限定了输出和原下标的对应。如果排序原数组,就可能破坏这种对应。

⚠️ 不要把“顺序表题不会就先快排”当万能方法;排序会改变顺序,也可能破坏稳定性或下标语义。

回源 · PDF 第 3 页 · b_3_6;PDF 第 3 页 · b_3_8;PDF 第 3 页 · b_3_9;PDF 第 3 页 · b_3_10

“没明说复杂度”就可以完全不管效率吗?

不能绝对化。讲义要表达的实战重点是:树、图题常有一条自然的遍历路线,题目若未要求额外优化,先把遍历逻辑写对。

但仍要做两项基本检查: - 不应无故重复遍历同一子树、边集或链表后缀。 - 如果题干或第(3)问要求复杂度,必须与代码实际执行路径一致。

因此应记成:无特别优化要求 ≠ 效率可以任意糟糕;只是先选自然、正确的线性遍历。

回源 · PDF 第 3 页 · b_3_0;PDF 第 3 页 · b_3_1;PDF 第 3 页 · b_3_2;PDF 第 3 页 · b_3_5

1.3 答题边界

“基本设计思想”应该写成什么样?

设计思想不是抄代码,而是用可执行的自然语言回答五件事: 1. 状态:维护哪些指针、数组、栈/队列或统计量? 2. 初始化:它们从哪里开始? 3. 循环/递归不变式:每一步已经保证了什么? 4. 更新与终止:如何推进,什么时候停止? 5. 输出:最后返回什么,失败时怎样表示?

这样写出的第(1)问可以直接对应第(2)问的代码块。

回源 · PDF 第 4 页 · b_4_4;PDF 第 4 页 · b_4_5

STL、main、头文件和过程函数到底写不写?

保守答题原则:不让库函数或一句“调用某算法”隐藏题目真正考查的核心过程。

  • 如果题目考快排、折半、树遍历等核心算法,就写出核心实现,不用 sort() 等一行代替。
  • 辅助性的栈、队列、min/max、交换等,若它们不是考点,可用规范伪代码或简短函数名,并注释语义。
  • 通常不需要展开 main 和头文件,但函数参数、返回值、头结点口径必须清楚。

⚠️ 讲义的“五行/四分之一代码”只是经验性启发,不是硬性评分规则;最终看这段是否为本题考查核心。

回源 · PDF 第 4 页 · b_4_0;PDF 第 4 页 · b_4_1;PDF 第 4 页 · b_4_2;PDF 第 4 页 · b_4_3

想不出最优解时,保底答案怎样写才有价值?

不能只写“暴力遍历”五个字,而要给出一个闭环的正确算法: - 明确枚举对象与范围,保证不漏、不越界。 - 写出更新答案或判定成功的条件。 - 写出无解、空结构、单元素等边界的返回。 - 如实标注时间、空间复杂度,不为“看起来优”而写错。

这个正确保底解同时是优化的参照系:优化后应与它在小样例上得到相同结果。

回源 · PDF 第 4 页 · b_4_6;PDF 第 4 页 · b_4_7