算法笔记写作规范

目标

算法笔记默认按 labuladong 风格整理:先讲问题和思路,再拆解状态/选择/遍历顺序,最后只保留 Go 代码,确保复习时能快速想起“为什么这样想、为什么这样写、为什么不会错”。

总体要求

  • 默认使用问题驱动的讲法,不从 API 或语法开始。
  • 默认只保留 Go 示例,不再混用 Python、C++、Java 等多语言并排展示。
  • 代码前先解释状态、变量、不变量和关键选择,避免“上来先贴模板”。
  • 能抽象成通用框架的算法,优先总结成「套路 + 例题 + Go 模板」。
  • 优先解释“为什么这样定义/为什么这样遍历/为什么这样剪枝”,这部分比代码本身更重要。

推荐结构

1. 一句话说明

用一句普通话解释算法:

  • 二分查找:每次扔掉一半不可能的位置。
  • 动态规划:把重复出现的小问题保存下来,后面直接查表。
  • Dijkstra:每次确认当前离起点最近的点,再用它更新邻居距离。

这一段要尽量口语化,像 labuladong 文章开头那样,让读者先建立直觉。

2. 适用场景

写清楚什么时候用、什么时候不能用:

  • 数据是否有序。
  • 边权是否非负。
  • 每个物品能选一次还是能重复选。
  • 问的是最大值、最小值、可行性还是方案数。

3. 原理

用生活化解释先讲直觉,再给正式定义。推荐先回答下面几个问题:

  • 这道题暴力做法是什么,瓶颈在哪。
  • 为什么这个算法能减少搜索范围或避免重复计算。
  • 每一步做出的“选择”为什么不会漏掉答案。
  • 关键不变量是什么。

推荐写法:

## 核心思路
 
先用一句话说明直觉。
 
## 为什么这样设计
 
解释这个选择为什么不会漏答案,为什么能减少计算。

4. 实现方式

不要只贴代码,先说明变量含义:

变量含义
left / right当前还可能有答案的范围
dp[j]容量为 j 时的最优结果
stack还没找到答案的一批候选元素
dist[x]起点到 x 的当前最短距离

5. 为什么这样实现

重点解释最容易忘的地方:

  • 二分为什么用 left <= right 或 left < right。
  • 0-1 背包为什么一维数组要逆序遍历。
  • 完全背包为什么一维数组要正序遍历。
  • 单调栈为什么被弹出的元素不会再成为答案。
  • Dijkstra 为什么不能处理负权边。
  • KMP 为什么失配时模式串可以跳到 next[j]。

如果是动态规划、回溯、树递归,尽量补出 labuladong 常用的三个视角:

  • 状态是什么。
  • 可选操作是什么。
  • base case 是什么。

6. 图解

优先使用 Mermaid、表格、ASCII 图或 SVG。简单流程用 Mermaid,局部状态变化用表格,复杂结构可以补 SVG。

flowchart LR
    A[问题] --> B[定义状态]
    B --> C[状态转移]
    C --> D[初始化]
    D --> E[遍历顺序]
    E --> F[返回答案]

6.1 动画

只有状态连续变化时才使用动画,例如排序交换、二分区间收缩、BFS 队列扩展。动画统一放在 附件/算法可视化/,例如使用 (附件 binary-search.gif 未随站点发布) 嵌入。

动画不能代替静态解释:同一篇笔记仍应保留状态表、Mermaid 或文字步骤,便于暂停阅读、全文搜索和打印。

7. Go 代码

代码块统一使用 go:

## Go 代码
 
```go
func solve(...) ... {
    // ...
}
```

要求:

  • 同一篇笔记默认只保留 Go 示例。
  • 如果需要多个版本,优先保留「基础版 + 优化版」两个 Go 实现,不再额外附 Python/C++ 对照。
  • 函数名、变量名尽量贴近题意,少用过度抽象的 foo、bar。
  • 复杂代码前可以加 1 到 2 行简短注释,重点解释不容易一眼看懂的转移、剪枝或数据结构维护。

8. 复杂度和坑点

复杂度要说明来源,而不是只写结论:

  • 时间复杂度为什么是 O(n log n)。
  • 空间复杂度主要消耗在哪里。
  • 哪些输入会退化。
  • 哪些边界条件最容易错。

题解补充模板

## 为什么想到这个算法
 
- 题目里的关键词:
- 暴力解法的问题:
- 该算法能优化的点:
 
## 状态 / 变量含义
 
| 名称 | 含义 |
|------|------|
|      |      |
 
## 执行过程图解
 
```mermaid
flowchart LR
```
 
## Go 代码
 
```go
func solve(...) ... {
}
```
 
## 易错点
 
- 

检查清单

  • 是否用一句话讲清楚算法在做什么。
  • 是否说明适用条件和不适用条件。
  • 是否把暴力思路与优化思路的差异讲清楚。
  • 是否明确状态、选择、base case 或关键不变量。
  • 是否解释核心变量含义。
  • 是否解释关键边界和遍历顺序的原因。
  • 是否只保留 Go 代码示例。
  • 是否有图解、表格或状态变化示例。
  • 是否说明复杂度的来源。

返回:算法学习导航