☰
刷题笔记方法论:从答案存档到可检索复盘体系
2026/10/13 19:04:53 网站建设 项目流程

2026-01-27 这天的晚上,我照常打开刷题平台准备把过去两周积累的题重新扫一遍。翻到两周前一道自己 AC 过的中等题,我盯着题目描述看了三十秒,脑海里只有一个模糊的轮廓:好像是用双指针?还是前缀和?最后我只能点开当时的提交记录,才勉强想起来当时的解法。

账号里的记录还在,代码也还在,但大脑中关于这道题的部分却像被格式化了。那种感觉很糟糕:刷题时间花掉了,笔记也写了,结果一个月以后照样忘。仔细翻了一下我的旧笔记,发现它们有一个共同特点——都把题目当“打卡项”,把笔记当“存底稿”,却忘了笔记最核心的用途:将来让你快速找回完整的解题思路。

所以从这天起,我开始重新整理自己的刷题笔记,从“做题打卡记录”改成“可检索、可重建、可复盘的学习资料”。这篇内容不是讲“刷多少道才能进大厂”,也不是讲“哪个题必须会”,而是分享一套我实测下来比较靠谱的笔记记录和复盘方法,以及我把这套方法落到实际题目上的完整示例。如果你也有自己的刷题笔记,不管它是存在本子上,还是写在文档里,这份记录也许能帮你少走不少弯路。

1. 为什么刷了 100 道还是像没刷:笔记变形的三种形态

在重写笔记之前,我先把旧笔记从头到尾翻了一遍,发现自己的问题特别典型,几乎都逃不过三种变形。

1.1 答案型笔记:复制题解,没有初始化

最早我写笔记的办法很简单:把官方题解或者高赞解法整段复制进来,题目、代码、注释,一应俱全。看的时候觉得特别踏实,感觉自己收藏了很多“标准答案”。

但复习的时候完全不是这么回事。复制的题解里没有我的思维过程,没有“我为什么在这个位置卡住”,也没有“我为什么从暴力解想到优化”。头脑没有参与整个推导链路,再看到时只是在读一段新文本,并不是在识别自己以前学过的内容。这有点像把别人的旅行攻略完整背下来,到了路口照样不认识路。

答案型笔记的最大问题就是“看似完整,实则无主”。它没有把外部知识转化成内部知识。我当时收藏了不下五十份这类题解,后来能主动回忆起来的,可能不超过五题。

1.2 代码型笔记:贴了代码,丢了决策

过了那个阶段以后,我开始只贴自己的 AC 代码。每次打开题目详情,把自定义过的代码段粘进去,再补一句“这题我过了”,就当作笔记完成。

这种笔记比答案型稍微强一点,因为代码毕竟是经过自己思考后提交的。但它同样丢掉了最关键的东西:决策过程。代码里只写了“做什么”,没有写“为什么这样做”;只写了循环和判断,没写“数组有序所以可以双指针”“子问题有重叠所以应该 DP”。过一两个星期,我看见这段代码能运行,却想不起当初为什么写得这么绕。

更典型的是,如果当初 AC 只是因为某个测试数据没戳中我的盲区,代码型笔记会让我误以为自己真的掌握了解法,因为代码看起来没有任何问题。等到换一组输入,马上就露馅。

1.3 无边界型笔记:只记录主路径,不记录边界

还有一类笔记,问题描述、解法、代码都在,但整篇只有一条路径:样例输入是什么,解法是什么,输出是什么。边界用例一概没有。

边界条件才是算法题真正的分水岭。空数组、全负数、只有一个元素、两个相同的最大值、整数溢出——这些用例往往决定了你答案的“通过率”。考试和实际项目里的测试,不会只给你主路径;它们最喜欢挑你笔记里没有写过的那个角落。

我自己的旧笔记里,很多题的“边界与反例”栏完全是空的。复盘时看着挺完整,下次遇到同款边界照样掉坑。后来我才意识到,没有边界用例的笔记,和没写过的笔记几乎没区别。

这三类问题让我明白一个道理:笔记不应该是题目的复印件,而应该是“我解决这道题时的推理痕迹”。有了这个认识,我才敢把它全部推倒重来。

2. 重建记录框架:一道题一条笔记,五个必备板块

想清楚笔记为什么失效之后,我给每道题重新规定了五个板块。五个板块对应五个问题:这道题让你做了什么?复杂度上限在哪里?为什么想到这个算法?哪些边界会踩坑?还能怎么变?五个都回答完,才叫“写过笔记”。

2.1 题意重述:把题干压缩成一句话模型

第一个板块不是抄题干,而是用一句话把题目抽象出来。比如“给定一个数组,求所有连续子数组的和的最大值”,这句话就是模型;“n 最大十万,元素范围是负一万到正一万”,这部分是约束。

一句话模型的作用非常大,它让你在复习时最快唤醒记忆。人的记忆不是按题目原样存储的,而是按“我把它理解成了什么”存储的。把题意缩减成一个带数据规模判断的短句,以后搜索和回忆都会特别快。

我写这个板块时还会特别标出数据规模。比如碰到n ≤ 10^5,我会记一句:这个规模下 O(n^2) 基本不可能通过,需要往 O(n log n) 或 O(n) 去思考。这样一来,后续的复杂度分析就不是空谈了。

2.2 复杂度基准:先给暴力解定一个上限

第二个板块,我会先把暴力解法写出来,再给它的时间复杂度。很多人觉得直接看最优解就好,暴力解没什么用。但我个人经验是:暴力解是最有价值的复杂度基准,它能帮你判断题目真正的难度来源。

举个简单例子,如果一道题暴力做法是枚举所有子区间然后求和,复杂度是 O(n^3),利用前缀和能降到 O(n^2),但 n 是十万,O(n^2) 依然不可行。这时候你自然知道:必须把复杂度压到 O(n) 或 O(n log n)。于是你去找能一次扫描解决问题的方法,题眼就会在过程中浮现出来。

数据规模是判断复杂度的关键信号。我常用下面这张表作为参考:

数据规模一般可以接受的复杂度
n ≤ 20指数级/阶乘级
n ≤ 10^3O(n^2) 甚至 O(n^2 log n)
n ≤ 10^5O(n log n) 或 O(n)
n ≤ 10^7基本只接受 O(n)
n ≤ 10^9基本只接受 O(log n) 或常数

这张表不是硬性定理,网络环境的常数项和题目本身都会影响实际判断,但它至少给了你一个推理的锚点。笔记里记下“暴力是 O(n^3)、期望最优 O(n)”,比单纯贴一句“最优解是 O(n)”要有用得多,因为它展示了思考路径。

2.3 模式与题眼:回答“为什么是它”

第三个板块是整个笔记的核心,也是最私人的部分。我不写“这里应该用动态规划”,而是写“我凭什么想到动态规划”。

比如看到“连续”和“区间和”,第一反应是前缀和;看到“最大/最小”并且发现当前状态可以从前一个状态转移出来,就会往动态规划靠。再比如看到有序数组和“查找某个值”,会想到二分;看到“连续不重复”之类的约束,会想到滑动窗口。这些联想就是题眼。

题眼不是标准答案,而是每个人的直觉捷径。把这种“为什么想到它”记下来,等于把下一次碰到类似题时的启动速度提高了不知道多少倍。我在笔记里经常会写一句话:“题目里有 XX 特征,因此优先往 XX 方向试;如果不成立,再退回暴力解分析。”

2.4 边界用例库:把踩过的坑都变成输入样例

第四个板块记录边界条件。空的输入、只有一个元素、全部是正数、全部是负数、重复元素、数字达到题目上限、答案会超过 int 范围等等,都属于边界。

我通常会把边界分成两类:一类是“题目本身的自然边界”,比如数组长度为 1 或元素全相等;另一类是“我写代码时踩过坑的边界”,比如某个变量初始化为 0,但在全负数场景下答案不应该是 0。后者尤其重要,因为那是真实经验,不是从题解里抄来的。

边界用例要写成可以直接跑的输入输出,而不是抽象描述。写“全负数 [-3, -4, -1] => 答案 -1”,比写“注意全负数情况”更有用。下次重做的时候,你只需要拿着这几个用例去验证代码,就能快速判断自己有没有犯老毛病。

2.5 变式推导:把单题升级成套路模块

第五个板块是变式推导,这也是我后来最喜欢的一部分。它的逻辑很简单:做完一道题,主动想一下“如果把其中一个条件改掉,解法要跟着怎么变”。

比如经典的“连续子数组最大和”,如果把问题改成“允许返回空子数组,结果至少为 0”,那只要把答案初始值从数组首元素改成 0。如果改成“求最大乘积子数组”,由于负负得正,就需要同时维护最大值和最小值。如果改成“环形数组”,可以先求普通最大连续和,再用总和减去最小连续和来绕过环形。

一次变式推导,等于把一道题扩展成两三道题,而且每道变式都在强化你对原题核心思想的理解。你的笔记也在不知不觉中从“单题答案”升级成“一类问题的解决方案”。

3. 复盘体系不仅仅是记:日清、周合、月索引

做好单题笔记只是第一步,真正让笔记发挥作用的,是一套固定的复盘节奏。我把它叫“日清、周合、月索引”,这套节奏是 2026-01-27 这天之后慢慢形成的。

3.1 当日 15 分钟的“趁热复盘”

所谓日清,就是每天刷完题之后,趁热把这道题整理进当天的笔记模板。我给自己规定的时间是 15 分钟。

为什么要限制 15 分钟?因为在刷题平台上 AC 之后,人会有一段短暂的“顿悟兴奋期”,这时候记忆还热乎,整理效率最高。如果拖到第二天,很多思维上的细节就已经丢了。但如果一道题非要花四十分钟才能写完笔记,说明我并不是真的懂,只是在抄解法和抄代码。

15 分钟里我会优先完成五个板块。如果哪道题我完全卡住了,正确写不出来,就不硬写,只在“一句话模型”和“重做记录”里标记一句“未完成,下次重做”。这个标记不是失败,反而是在提醒自己,这一题仍然欠着债。第二天回来补的时候,往往理解得比当天硬撑着写更深。

3.2 每周合并同类题,形成套路树

每周日,我会把这一周积累的新题全部过一遍,然后做一件和“单笔记”不同的事:合并同类题。

举个例子,这周做了三道二分边界题、两道滑动窗口题、一道差分数组题,我就把三道二分题归到一个文件夹/文档里,再把它们对答案初始值、循环条件、边界移动方式的处理做一次横向对比。这样笔记就从“每道题一个文件”变成了“每条套路一串记录”。

我后来把这叫套路树:根是算法主题,枝干是变体,叶子是具体题目。不这么做的话,笔记再多,也只是平行摆放的条目,无法形成知识间的连接。而面试和工程项目里面,真正难的不是背下某个解法,而是快速识别当前问题属于哪个套路树分支。

3.3 月度反向索引:从模式往回找题

月底时,我会做第二件更重要的事:建反向索引。也就是把过去四周各个套路树下积累的题,按“模式”而不是按“日期”重新排出来。

反向索引的格式类似一张表:左边是模式名,比如“二分求左边界”“滑动窗口固定长度”“状态压缩 DP”,右边是这个模式下的代表性题目和我定的“一句话模型”。遇到新题的时候,我先扫一眼这个索引,看它的特征和哪一行的模式描述更接近,然后直接打开那一行后面的笔记,比在没有结构的收藏夹里翻找快得多。

这个习惯彻底改变了我的笔记可用性。过去我要靠回忆题目编号去找笔记,现在只要靠特征匹配就能定位。日期标签很自然地被弱化,但并不会消失。比如 2026-01-27 的笔记,索引里也可能写着“动态规划/滚动数组”,当月的所有题目都进了月度索引之后,那天的记录就不再只是孤零零的打卡项。

3.4 重做时只留下一条线索

复盘环节里还有一步容易被忽略:重做。我定的重做规则是,一不看完整题解,二不看完整笔记代码,只允许打开笔记的一行“一句话模型”和一两个边界用例,然后关掉页面,自己在编辑器里重新写题。

如果顺畅通过,我会在笔记的“重做记录”里打上通过标记。如果卡住,我会把卡住的位置记下来,比如“始终没搞懂为什么循环条件是 left < right”,这比写“没做出来”有用得多。下次复盘时,我就知道重点补哪里。

重做的间隔不必固定。我个人习惯是当天记录后,隔两天一次,再隔一周一次,最后到月底跟月度索引一起过一遍。每次重做都是对记忆引路的检验,比“再看一遍笔记”有用得多。

4. 一份可复用的模板,以及我当天的完整示例

说了这么多抽象方法,下面把模板和实际示例直接放出来,你可以照着这个思路改造成自己的版本。

4.1 模板骨架:Markdown 结构可以照抄

我目前用的模板大概是下面这样,比较简单,没有花哨的样式。

# 题目层:类型/一句话模型 ## 题意重述 - 一句话模型: - 输入规模: - 数据范围: ## 复杂度基准 - 暴力解: - 最优解: - 时空复杂度: ## 题眼与模式 - 看到什么信号? - 为什么想到该算法? - 关键转换: ## 边界与反例 - 用例 1 - 用例 2 ## 变式 - 变式 1 - 变式 2 ## 重做记录 - 第一次重做(日期):通过/卡点 - 第二次重做(日期):通过/卡点

如果碰到简单题或已经没有新意的题,我不会非要填满所有板块。模板是脚手架,不是考试题,把每个框都填满反而会拖慢速度。

4.2 一份“连续子数组最大和”的完整笔记

下面是一份根据真实刷题经验整理出来的完整示例,题目是很常见的“求连续子数组最大和”。为了不依赖原题编号,我直接用问题描述开头。

### 连续子数组最大和 | 动态规划/前缀和 - 日期:2026-01-27 - 一句话模型:给定整数数组 nums,求所有连续子数组和的最大值 - 输入规模:n ≤ 10^5,元素范围 [-10^4, 10^4] ## 复杂度基准 - 暴力解:枚举所有子区间并求和,O(n^3);用前缀和优化后 O(n^2) - 最优解:O(n) 时间,O(1) 空间 ## 题眼与模式 - 信号:连续子数组 + 最大和 => 子问题有重叠,适合动态规划 - 关键状态:dp 表示以当前位置结尾的最大连续和 - 转移:dp = max(x, dp + x) - 答案:全程 dp 的最大值 ## 边界与反例 1. 全负数 [-3, -4, -1] => 答案 -1,不能初始化为 0 2. 只含一个元素 [7] => 答案 7 3. 全为零 [0, 0] => 答案 0 ## 变式 1. 允许空子数组,答案至少为 0 => 答案初始值从 nums[0] 改为 0 2. 求最大乘积子数组 => 需要同时维护最大值和最小值,负负得正 3. 环形数组版本 => 最大和 = max(普通最大和, 总和 - 最小子数组和) ## 重做记录 - 第一次重做(2026-01-27):只看“一句话模型”和“边界”,独立写出,通过

这份笔记的核心代码只需要短短几行,贴在题眼下面方便回溯:

dp = 0 ans = nums[0] for x in nums: dp = max(x, dp + x) ans = max(ans, dp) print(ans)

注意ans初始化为nums[0],而不是 0,这样全负数用例才不会得出错误答案。很多初看我笔记的人都会在这里愣一下,但边界用例已经提前解释清楚了。

4.3 我会用到的快捷标记

为了让笔记在日后扫描时更快,我会用一些简单的纯文本标记。没有复杂的样式,只是统一布点。

标记含义
一句话模型题目抽象后的核心描述
数据集规模判断复杂度的重要依据
题眼从题目特征到算法选择的联结点
边界最容易出错的特殊输入
变式同一个模型的其他约束条件
重做:通过重新独立完成,说明已掌握
重做:卡点记录卡住的具体原因,待补

4.4 模板落地时最常出现的四个问题

第一,把模板当成逐字填空。有些题确实没有变式,或者边界已经被题目明明白白限制了。这时候空着变式栏是合理的,硬凑一个“变式”只会降低笔记参考价值。

第二,把大段代码贴进笔记当正文。代码应该是辅助理解,而不是笔记主体。如果整页都被代码占据,那叫代码存档,不叫笔记。真正需要唤起记忆的,是题眼和边界,不是代码本身。

第三,不记录日期。没有日期的重做记录没法判断间隔,也没法验证自己是不是真的记住了。日期在笔记系统里其实是一种节奏数据,长期积累后你可以知道自己遗忘最快的题型是哪些。

第四,把复杂度表当成绝对标准。我前面给的“n ≤ 10^5 就 O(n)”,只是普通情况下的参考。如果题目自身带很强的缓存或剪枝条件,实际表现可能不一样。但笔记里必须记一个判断依据,哪怕是“经验上觉得 O(n^2) 危险”,也比什么都写不出来强。

5. 长期坚持的几个习惯,来自真实记录

最后这部分,与其说是方法论,不如说是我在整理刷题笔记半年后的几条私人体会,每一条都是从踩坑和调整里得来的。

5.1 允许自己写“半成品”笔记

以前我总觉得,笔记要么不写,要写就必须完整。结果就是许多难懂题因为“今天写不完”而完全没有笔记,等到复习时更加无迹可寻。

后来我接受了一个设定:笔记可以有“欠账”。遇到困难题,我先记一句话模型和题眼,把“复杂度基准”和“变式”留空,再在重做栏标一个“未完成”。过两天重做时把这些空补上,反而比我硬撑着一次性写完理解得更透。所以不必追求每张笔记都完美,但每道刷过的题至少要留一个能被检索到的入口。

5.2 把“一句话模型”写进标题,方便以后搜索

这也是我从 2026-01-27 这天才开始改的习惯:标题不要用“题目编号”或简单日期,而要用“算法类型 + 一句话模型”,比如“二分/求左侧边界”“滑动窗口/最长无重复子串”“DP/连续子数组最大和”。

这样当你面对一道新题,感觉像某类套路时,直接搜索“滑动窗口”,就能把这些题从各个日期里全部捞出来。标题是一套笔记系统里真正被搜索的入口,如果入口设计得不好,内容再全也白搭。

5.3 重做优先于重读

在我体验过的所有复习方式里,最有效的是不看笔记独立重做,而不是反复重读笔记。重读会让人产生“我会了”的错觉,因为它全程有提示;重做则是强制你自己把推导过程走完。

我现在的做法是,同一道题至少安排三次重做:第一次在记录后的两三天,第二次在一周后,第三次放在月度索引建立时。每次重做只看一句话模型和边界用例,其余全部关掉。能独立做出来就打上通过标记,做不出来就记录卡点。

这样坚持下来,最大变化是,我碰到旧题时不再是“眼熟但想不起来”,而是真的能在几分钟内把思路重建出来。刷题笔记的意义,说到底不是收藏,而是在需要的时候能重新推演一遍。如果你也在刷题,我建议你从今天开始,把笔记里的“答案型内容”换成“线索型内容”,哪怕只改掉一道题,下一次复习时也能明显感觉到差别。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询