资讯详情

资讯详情

打造高效算法刷题本:从设计模板到知识体系

算法刷题本这三个字拆开看不像什么新鲜事不就是题目、讲解、代码三段式吗但真能把这三块同时做扎实的人我身边并不多见。大部分人的刷题记录要么是一堆来不及看的题解链接要么是粘贴板上贴了一整页代码却没留下任何思考痕迹。我自己这个刷题本前后折腾了快一年从最初只会抄答案到后来逐渐形成一套适合自己的整理方法中间踩过的坑基本都踩了一遍。如果你也准备系统刷算法题或者正在备技术面试、算法竞赛那这篇总结应该能帮你少走一点弯路。本文分享的重点不是某一道具体题目的答案而是围绕“题目 题目讲解 代码实现”这套结构讲清楚刷题本应该怎么设计、怎么分类、怎么写讲解、怎么写代码以及后期怎么维护才能不烂尾、真正变成可复用的知识资产。适合准备面试的开发者、想冲竞赛的学生也适合每一个刷题刷到迷茫、感觉“题做了很多但脑子还是空”的人。1. 整体设计刷题本不是题库是写给自己的教材1.1 刷题本要解决的真实问题先说清楚刷题本到底在对抗什么。我复盘过自己刷题的前三个月发现一个特别扎心的规律一道题当时看懂了两周之后再见除了隐约记得“好像是用二分”其他全还给答案了。这种“假学习”的现象不是个例根源在于我们的大脑很容易把“看懂了别人的思路”误认为“自己会了”。所以刷题本的第一个职责就是对抗遗忘让每一道题都留下可检索、可复习的思考脚印。第二个问题是思维碎片化。今天刷一道字典序问题明天刷一道区间合并如果只是按随机顺序记录那刷到第两百题的时候笔记里就是一堆彼此孤立的点形不成线、更织不成网。真正有效的刷题本应该以专题为骨架把同一种算法或者同一个数据结构的题放到一起让题与题之间产生关联这样复习的时候你看到的不只是一个题而是一类题的通法。第三个问题更现实当你积累了三百道题之后复习成本会高到惊人。如果没有统一的格式、清晰的标签和准确的难度标注你根本不知道考前应该看什么。所以刷题本本质上是一份给自己用的“二次教材”它的核心价值不是收藏而是筛选、压缩、重组。我在设计整个笔记库时给自己定了三条铁律专题聚合大于随机记录、能讲给别人听才算真懂、随时能找到才算有效积累。后面所有模板和习惯都是围绕这三条展开的。1.2 整体目录结构与单题模板有了定位接下来就是结构设计。我的刷题本用 Markdown 加 Git 管理目录长这样algorithm-notes/ ├── 00-template.md # 单题笔记模板 ├── 01-binary-search/ │ ├── README.md # 本专题总结与索引 │ ├── search-first-ge.md # 查找第一个大于等于 target 的下标 │ ├── peak-index.md # 山峰数组峰值查找 │ └── split-array-sum.md # 二分答案专题 ├── 02-two-pointers/ │ ├── README.md │ └── ... ├── 03-dynamic-programming/ │ ├── README.md │ └── ... └── 99-review/ ├── weekly-review.md # 每周随机点题复习 └── bug-list.md # 常错边界清单每个专题文件夹下第一份一定是 README用来汇总这一专题里所有题的套路、易错点和“一句话思路”相当于专题的压缩包。单题笔记则统一使用模板我的模板经过三次改版最终稳定成这个结构# 题目名称自评难度入门/中等/挑战 ## 考点标签 数据结构数组 | 算法范式二分查找 | 易错点边界条件 ## 来源与场景说明 在线评测平台 / 某模拟项目 / 面试高频场景 ## 我的第一想法 拿到题目后自己最初的思路哪怕很笨 ## 卡壳点 哪里卡住了为什么卡住 ## 最优解法推导 从暴力解到最优解的每一步优化重点写动机 ## 边界条件 空输入、单元素、溢出、重复值 ## 代码实现 带关键注释的代码块 ## 复杂度分析 时间O(?) | 空间O(?) ## 复盘日期 YYYY-MM-DD方便安排复习很多朋友看到这个模板的第一反应是“每道题都写这么多太费时间了”。我的体会是前三十题确实慢但你一旦写熟大部分字段只需要几分钟。而且真正值得写详细的不是每道题的全部内容而是“卡壳点”和“最优解法推导”这两块因为这两个字段记录的是思考过程不是答案本身。复制粘贴答案没有任何成长把思考过程写下来才算把这道题变成自己的东西。2. 选题与归类刷题数量不等于知识密度2.1 从“刷多少”到“怎么选题”的思维转变我刚决定刷题时也犯过“数量崇拜”的毛病总觉得刷到五百题、一千题就稳了。后来发现这个目标本身就很有问题刷题刷的是算法思维不是题目编号。有些人刷三百题比另一些人刷八百题的效果好得多差别就在于选题方式。我最开始是“看到什么刷什么”热门榜单按顺序往下做结果就是前一百个题里大量重复的简单题反复刷难题和中档题反而没覆盖到知识密度低得可怜。后来我把选题策略改成了三维度控制第一个维度是知识点覆盖度。核心算法和数据结构每个至少要保证五到八道题形成一定量。第二个维度是难度梯度。每个专题里入门、中等、挑战的比例控制在三比五比二左右。为什么挑战题只占两成因为挑战题通常是多个套路组合如果基础不牢直接上难题大概率只能抄答案收获反而不如把中等题吃透。第三个维度是形态多样性。同一个算法尽量在不同的载体上练比如二分查找不光要在数组里练还要在旋转数组、答案区间、矩阵搜索里练这样才能把“二分”从一道题升级成一种条件反射。选题还有一个隐藏原则优先选“暴力解到最优解有明显演进路线”的题。这种题最适合放进刷题本因为它的讲解能写出完整的思考链条而不是只会一句“这里套个模板就完事”。我在每个专题里都会刻意找两到三道这样的“示范题”把它们写得很深其他同套路的题则可以写得精简一些。2.2 专题划分与标签体系的设计选题解决了“刷什么”接下来是“放哪”。我的分类体系是用两条轴交叉一条轴是数据结构包括数组、链表、栈和队列、哈希表、树、图、堆、字符串另一条轴是算法范式包括枚举、贪心、递归回溯、DFS/BFS、二分、双指针、滑动窗口、动态规划等。一道题在笔记里只归属一个专题文件夹但通过标签系统可以跨专题引用。标签是我后期才意识到的重要设计。没有标签的时候我想找一个“考察了边界溢出”的题得把所有笔记翻一遍。加了标签之后一条查询命令就能筛出来。我的标签设计成这样标签维度常用示例作用数据结构数组、链表、树、图决定用什么容器组织数据算法范式二分、双指针、动态规划决定用什么策略解题自评难度入门、中等、挑战用于安排复习优先级状态标记已掌握、需复习、重点配合周复习做调度易错点边界、溢出、重复元素用于错题回顾与 bug 清单这个标签体系不用一开始就设计得特别完美可以先随手打然后每两周做一次“标签重排”把所有没有标签或者标签混乱的题梳理一遍。重排的过程本身也是一次低成本复习你会发现很多题当时打错标签其实是思路没理清重新归类之后你对这个算法的理解反而更清楚了。再说一下专题划分的粒度。我的原则是宁粗勿细一个专题放五到十五题就够了。太多说明分类过粗太少说明分类过碎。比如“动态规划”这个专题我一开始拆成了“线性 DP”“背包 DP”“区间 DP”“树形 DP”四个文件夹结果每个文件夹下只有两三道题复习的时候反而失去整体感。后面我把它们合并成一个动态规划文件夹用标签区分子类型复习效率明显提升。3. 题目讲解的写作方法把“会做”变成“会讲”3.1 一条合格的讲解要回答的四个问题刷题本里的题目讲解难点不在于字数多少而在于视角。很多人的笔记是这样写的“这题用二分查找时间复杂度O(log n)。”没了。这本质上只是把题解里的一句话抄了过来完全没有信息量。一条真正有用的讲解至少要回答四个问题。第一这道题在考什么是单调性、最优子结构还是边界条件的精细控制第二最笨的办法是什么很多人跳过暴力解直接写最优解这是大忌因为暴力解才是整个思考链条的起点它能告诉你问题的天然复杂度在哪里。第三暴力解卡在哪里是重复计算太多、搜索空间太大还是状态数量爆炸这一句“卡点”就是优化的动机。第四怎么一步步从卡点走到最优解这才是我理解的“讲解”。除了这四个问题还有两个加分项边界条件的系统性梳理以及“为什么这个复杂度已经不能更低”的下界分析。这两点做得好讲解的深度会直接上一个台阶。我在模板里加“我的第一想法”和“卡壳点”这两个字段就是为了逼自己在看答案之前把前三个问题先过一遍记录下真实的思维状态。哪怕第一想法是错的这个记录也比事后抄一段官方解析有价值得多。3.2 从暴力到最优一道二分题讲解的完整示例理论讲完还是用一个具体例子演示一下我的讲解长什么样。就以“在一个升序数组中找到第一个大于等于目标值的位置”为例这是一个很常见但又特别适合练手的二分变式。这道题的题目复述是给定一个升序排列的整数数组 nums 和一个整数 target返回第一个满足 nums[i] target 的下标。如果不存在则返回数组长度 n。我拿到题目后的第一想法是直接从左往右扫一遍遇到大于等于 target 就返回走到底都没有就返回 n。这是最直觉的解法时间复杂度 O(n)。卡壳点在于怎么用二分普通二分是找相等的目标值但这个题找的是“第一个满足不等式的点”边界该怎么取舍接下来是推导过程。因为是升序数组数组天然具有单调性所以可以用二分不断收缩区间。关键在于维护一个“不变量”区间 [left, right) 内可能存在答案且答案一定在右边界内。于是每一步比较 nums[mid]如果它小于 target说明 mid 及其左边都不可能是答案把左边界收紧到 mid 1否则mid 可能是答案但不排除左边还有更小的答案于是把右边界收到 mid。循环结束后 left 所指的就是第一个大于等于 target 的位置。实现时有一个容易被面试追问的细节为什么 mid 要写成 left (right - left) / 2而不是 (left right) / 2答案是防止两个大整数相加发生溢出。这在工程上是真实存在的风险虽然刷题时数组长度可能不会那么大但写成前一种形式是一种更安全的习惯。同理右边界初始值取 n 而不是 n - 1是为了同时处理好“答案不存在”的语义。边界用例也很清晰空数组返回 0所有元素都小于 target 返回 n所有元素都大于等于 target 返回 0。复杂度自然是 O(log n) 时间、O(1) 空间。复盘笔记里我还额外记了一笔我第一次写这段代码时把 right 的更新写成了 right mid - 1结果在数组长度为 1 的情况下直接死循环。这个错误特别典型原因是二分模板的左闭右开区间和闭区间两种写法混用了。把这个错误记录在卡壳点里比做十道新题都值。3.3 一题多解与复杂度分析记录的加分写法刷题本对同一道题如果存在多种经典解法我通常会单独开一个小节做对比分析。拿“数组中出现次数超过一半的元素”这道经典题为例讲解部分我会列三种解法哈希表计数、排序取中位、摩尔投票。光列解法不算完还要写出数组在三者之间切换的思考过程。哈希表计数是最好想的思路时间 O(n) 但空间也是 O(n)问题在于额外占用了存储。排序取中位则利用了“多数元素一定在中间位置”的性质时间升到 O(n log n)但可以做到 O(1) 额外空间。摩尔投票的思路更妙它让不同元素互相抵消最后活下来的就是多数元素时间 O(n)、空间 O(1)代价是需要你先理解“抵消”背后的不变量。这类一题多解的笔记我还会在末尾画一个对比表列出解法、时间复杂度、空间复杂度、适用场景四列。比如哈希表适用于数据范围大但内存充足的场景摩尔投票要求“存在出现次数超过一半的元素”这个前提排序法不适合数据流场景。提醒一下这里说的“画表”不需要用什么复杂工具Markdown 表格足够重点是逼自己思考解法之间的取舍关系而不是把它们并列摆在一起就完事。这种对比思考面试里被追问“为什么不用另一种解法”的时候特别管用。4. 代码实现里的工程细节不是能过样例就叫完成4.1 代码结构和注释是留给未来的自己看的刷题本里的代码跟赛场上提交的代码是不同的物种。赛场上追求的是最短时间写对而刷题本里的代码要承担“教学示范”的责任三个月后的你要能一眼看懂并快速复用。所以我在代码画面上有四个硬性要求命名自解释、关键分支必须有注释、核心函数单独拆分、不写炫技缩写。命名自解释这点最容易被忽略。写题练习时变量名可以用 i、j、k但放进刷题本的代码我会改成 left、right、mid、count、cur_sum 这种有明确语义的名字。很多同学觉得这是浪费时间其实不然一个清晰命名的版本复习时根本不用读注释就已经能猜出代码意图这才是高效复习。我推荐的模板是给核心函数写一小段头注释注明输入输出和边界语义然后在策略发生切换的关键分支写一两句注释完全没有必要逐行注释。举个例子同样是二分边界处理两个版本差别很大def find_first_ge(nums: list[int], target: int) - int: # 返回第一个 nums[i] target 的下标不存在则返回 n left, right 0, len(nums) while left right: mid left (right - left) // 2 if nums[mid] target: left mid 1 else: right mid return left这段代码我在刷题本里还额外写了一句注释“右指针定义成开区间所以更新时 right 直接取 mid不写 mid - 1。”看上去只是一句自言自语但这句话就是曾经让我死循环的教训写上之后以后复习到这道题就再也不会踩同一个坑。4.2 边界条件与自测用例的检查清单代码能过样例不等于代码正确。我在这个刷题本里给自己强制加了一条规矩每道题写完后至少列出五个边界用例然后逐个在脑子里跑一遍。这份边界检查清单我固定放在代码下方不同数据结构题型会有不同侧重。拿数组二分类的题来说我通常检查以下用例用例类型具体输入期望结果空输入[]target5返回 0单元素[5]target5返回 0元素重复[1, 3, 3, 3, 5]target3返回 1目标在开头[2, 3, 4]target2返回 0目标不存在且位于区间内[1, 4, 6]target5返回 2全小于目标[1, 2, 3]target9返回 3这种测试清单的维护成本很低但收益极高。我统计过自己刷题本的 bug 记录大概四成错误都出在边界上尤其是单元素、空输入、全部大于或全部小于这三类。把边界用例固化成习惯之后很多 AC 之后才发现的隐藏错误在写代码阶段就能被消灭掉。另外还要提醒一个常见误区很多人公布代码时会删掉自测部分只留主函数。这其实很可惜。我建议把自测用例保留在代码块下方的“边界条件”小节里这样复习时可以直接拿来构造测试等于给未来的自己做了一轮回归测试。4.3 与讲解联动让代码和思路一一对应代码不是孤立的存在它要跟讲解部分形成联动。我常用的做法是在代码的关键行加数字标注比如# ① 左指针更新、# ② 右指针保持开区间、# ③ 循环退出后 left 即答案然后在讲解部分用同样的① ② ③去引用。这样看代码时能迅速定位到思路推导的位置看思路时又能马上跳到对应实现复习体验会顺很多。联动还有一个层面是版本管理。我是用 Git 管理整个刷题本的提交信息会写成类似“修改第X题修正右指针更新逻辑补充空数组用例”这样的格式。这个习惯听起来很工程师实际操作起来很简单却能帮你应付一个很常见的危机某一天你发现新写法反而引入了 bug需要退回上几版对比。没有版本记录的时候这种回溯几乎不可能实现。我对自己的要求是每次改动只聚焦一个主题commit 信息写清楚这样整个刷题本的历史就是一份很完整的“算法自我进化史”。5. 常见问题与维护技巧刷题本从入门到不烂尾5.1 高频问题速查表刷题本这东西最大的敌人不是内容难写而是坚持不下去。我把自己在使用中遇到的典型问题整理成了一张速查表如果你正在维护自己的刷题本可以直接对照自查现象根源解决方案刷完就忘笔记只抄题解没有思考痕迹每道题强制写“我的第一想法”和“卡壳点”讲解像翻译没有自己的卡壳记录只是在复述先独立做一遍再对照答案补充遗漏代码过样例但出错边界用例覆盖不足按检查清单补空数组、单元素、溢出等用例专题分类越来越乱一开始分类过细或没有标签每两周做一次标签重排笔记越积越多不敢复习没有优先级复习成本过高通过状态标签 自评难度安排复习顺序坚持不下去目标定太大每道题都长篇大论降低单题成本只写关键内容每天一题这六类问题我基本都踩过。其中“讲解像翻译”这一点我认为最隐蔽因为它表面上看很努力实际上没有任何思考增量甚至会让你的笔记变成一篇大型错题抄写现场。我在第三次改版刷题本时把所有“读起来像是在复述题解”的段落全部删掉重写换成自己推导时的真实犹豫那一次删改之后整个笔记的质量完全不一样了。5.2 让刷题本能被坚持维护的四个习惯刷题本要长期维护靠的不是意志力而是让它成为一个低摩擦的习惯。我实践下来最有用的四个习惯分享给你。第一是“11”日任务。每天一个新题加一个旧题复盘。旧题复盘不是重做而是只看“卡壳点”一栏在脑子里把解题流程过一遍如果卡壳点已经能顺畅想通就把状态标签从“需复习”改成“已掌握”。这个动作每天只需要五到十分钟但能让笔记里的状态数据一直保持新鲜复习优先级永远准确。第二是每周随机抽取。每周随机抽三到五道笔记里的题遮住代码只留题目复述然后重新在纸上推导一遍。这个习惯的设计初衷是防止“笔记里写得漂亮实际一上手全忘”的情况。随机抽取能打破你按顺序复习时的路径依赖逼迫大脑从零开始建立思路。第三是每月一次的专题 README 更新。每当一个专题新增了一些题就刷新这个专题的 README用半页压缩该专题的通法适用条件、关键模板、常见卡壳点。这个月更动作是刷题本从“做题记录”升级为“知识地图”的关键一步。第四是给自己设“烂尾保险”。如果哪一天实在不想写完整讲解那就允许自己只写一个“一句话题解”占位但要求必须在三天内补上完整版。这道保险极大地降低了每天的心理门槛因为最小行动成本够低坚持反而更容易。5.3 把笔记变成考前冲刺材料等刷题本积累到一定量级它还有一个非常实际的用途变成考前两小时的冲刺材料。方法是在每个专题的 README 里维护一张“必背索引表”大概长这样考点路径最佳解法复杂度一句话思路查找首个大于等于目标值二分左闭右开O(log n) / O(1)不断收缩存在答案的区间查找多数元素摩尔投票O(n) / O(1)不同元素抵消剩余即多数区间合并排序 贪心O(n log n) / O(log n)按起点排序后依次合并重叠区考前我只看这两页表格不看完整的几百道题。这张表上的“一句话思路”写得好不好最能检验你对这道题的理解深度。如果你发现自己一分钟内想不清楚那句话在说什么那说明原题笔记中的讲解还需要修正这本身就是一次高质量的复习反馈。把这张表维护好刷题本就从“学习工具”变成了“应试地图”价值完全是另一个量级。6. 从刷题本到个人知识体系下一步扩展6.1 从单题笔记到专题总结当某一个专题积累了足够多的题目之后我会发现很多解法之间共享着同一套思维框架这时候就应该从“逐题记录”提升到“专题总结”。以二分查找为例做完十几道题之后套路就开始浮现先判断问题是否具有单调性再确定搜索区间形态是闭区间还是左闭右开接着写出 while 循环和边界更新逻辑最后单独处理“不存在”的情况。把这些共性提炼出来写进专题 README就形成了一套属于你自己的“解题框架”。框架形成之后的效果是很明显的以后遇到同类的新题你不再是从零开始摸索而是先在框架里定位它的不同点然后针对不同点做局部调整。我在读完自己写的二分专题总结之后再看新题“这道题其实就是二分套上了一层额外条件”的识别速度明显加快。这就是从刷题本过渡到知识体系的第一步题量积累到一定程度总结沉淀出框架再用框架去指导新题。6.2 从刷题本到模板库与面试表达最后一步扩展是把刷题本里反复出现的代码模式抽成一份独立算法模板库。模板不是抄代码而是把核心流程的骨架和变式都写清楚。还是拿二分举例模板库分为三段标准二分、第一个满足条件的二分、答案二分。每个模板都标注适用前提、边界更新规则、常见陷阱。这样做的好处是当面对新题时你脑子里装的不是五十道零散的题而是十几个可以灵活变换的模板。模板库和刷题本之间的关系是刷题本负责记录具体题目的推导和错误模板库负责承载抽象出来的通法两者互相引用。我在面试季做模拟练习时还有一个附加动作拿着模板库里的模板不看任何资料用三分钟口头讲解一遍模板的思路、复杂度和边界。这个过程本质上是把“会写”转化成“会讲”而会讲才是面试真正考察的能力。把刷题本维护到这个程度它就不再是一份考古记录而是一套能持续进化的个人算法知识系统。最后再分享一个小技巧。我写这个刷题本最大的转折点发生在某一天我删掉了将近一半的笔记——那些只有代码、没有任何讲解痕迹的笔记留着只会让我产生“我已经刷了很多题”的错觉。删除之后刷题本瞬间变薄但每次翻开它我都会感觉每一条记录都有持续产出的能力。这个过程让我真正体会到刷题本的价值从来不在数量而在密度。哪怕你一个月只整理十道题只要每一道都能回答清楚它考什么、怎么优化、边界在哪、当初卡在哪这十道题带给你的成长也会远超三百道剪贴板里的题。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →