☰
代码随想录刷题全记录:系统化备战算法面试的实战方法
2026/10/1 3:11:44 网站建设 项目流程

我第一次系统性地用《代码随想录》刷题,是在准备跳槽的第三个月。那时力扣已经刷了两百多道,但每天打开一道新题,脑子依然一片空白。朋友看我不对劲,丢了一份代码随想录题单给我,让我先别碰难题,从数组、链表这些基础章节按专题老老实实过一遍。我嘴上答应,心里觉得浪费时间。执行两周之后我才意识到一个扎心的事实:我缺的从来不是刷题数量,而是刷题的系统性。

这篇文章,就是我把这套方法重新刷完一轮之后的完整记录。它适合三类人:正在准备校招或社招面试的求职者,刚转行编程、数据结构还不熟的新人,以及刷洛谷刷到瓶颈、想回头补基础模型的竞赛入门选手。看完你至少能回答三个问题:刷什么、按什么顺序刷、刷到什么程度才算真的会了。

1. 代码随想录到底解决什么问题

1.1 为什么你刷题刷到怀疑人生

先说一个最常见的现象:很多人刷题不看体系,只按热度排序,今天做一道链表,明天做一道图论,后天再来一道动态规划。大脑接收到的全是碎片,无法形成“模式识别”。什么是模式识别?就是你看到“连续子数组”“最长子序列”“区间最值”这类字眼时,能本能反应出可能涉及哪些算法。这个能力只能通过集中轰炸同一类题目建立。随机切换题型,等于今天练篮球、明天练游泳、后天练举重,每次都有新鲜感,但肌肉记忆始终为零。

再看题解依赖。大多数人的刷题流程是:题目不会→打开题解→恍然大悟→把代码提交通过→关掉页面。过两周,同类型的题换个条件,又不会了。你“看懂了”和“能写出来”之间,隔着一层输出能力,而输出能力只能靠关掉答案自己写来练。题解看多了会产生一种虚假的掌控感,让你误以为知识已经进入大脑,实际上它只停留在视网膜上。

最后是数量崇拜。一天刷十道、二十道的打卡,大部分时间花在复制粘贴和跑通样例上。这些题根本不会进入长期记忆。代码随想录的思路恰恰相反:它把题量压下来,把每个专题的核心题反复讲透,先让大脑建立结构,再用变体题填充细节。我自己体会最深的是二叉树这一章,之前零零散散做过三十多道相关题,真正把前中后序遍历、层序遍历、最近公共祖先这些集中重刷之后,才第一次觉得“树的题有套路”。

1.2 这套题单是怎么组织的

代码随想录的题单不是简单把力扣题目按编号堆起来的。它的章节顺序基本是:数组→链表→哈希表→字符串→双指针→栈与队列→二叉树→回溯→贪心→动态规划→单调栈→图论。这个顺序有明显的知识依赖关系。数组和链表是所有容器的基础,先拿它们练遍历、插入、删除;哈希表训练空间换时间的思维;二叉树是递归的启蒙场;回溯、贪心、动态规划又都建立在前面几种数据结构之上。按这个顺序走,每一步都能踩在上一步的积累上。

每个专题内部又分“重点题”和“拓展题”。重点题用来立模板,拓展题用来检验模板能不能变形。比如二分查找专题,先从最基础的力扣704开始,再引到搜索插入位置、在排序数组中查找元素的第一个和最后一个位置,所有变化都围绕左右边界做文章。我见过不少人的刷题记录是从中间某个难题开始的,刷的时候很兴奋,最后反而连最基础的二分边界都写不对。另外容易被忽略的是,这套题单的很多题解后面都写了“一刷、二刷、三刷”的间隔重复建议。刷题不是一次性的消费行为,而是需要反复回到旧题上巩固的长期过程。

1.3 哪些人最适合跟着它刷

如果你是时间紧的面试党,这种按专题刷的方法比按题号刷高效得多。数组、链表、二叉树、回溯、动态规划,基本覆盖了大多数公司手撕代码的高频考点。按专题刷过一轮之后,再做力扣的每日一题就会轻松很多。如果你是转码新人,章节递进刚好能补上数据结构课没建好的框架,不会出现“学了链表但不会用,学了递归但不敢写”的尴尬。如果你是竞赛初学者,洛谷上的题往往按难度而不是按算法分类,你很容易“看得懂题但不知道用什么算法”,回到这个题单做专题检索,能快速补上模型盲区。

当然也有不适合的情况。已经系统学过算法、且自身方法论成熟的人,把时间花在基础题单上收益有限,应该直接去打比赛或刷高级题保持手感。判断标准很简单:你能不能不看任何资料,把每一类核心题的核心模板完整写出来。能,就不需要按部就班跟了;不能,那就老实从第一个专题开始。

2. 开始刷题前的准备:目标、节奏和复盘

2.1 先想清楚目标再打开题库

我见过太多人一上来就问“一天刷几道能拿到Offer”,这个问题本身就问错了。不同目标对应完全不同的刷法。如果是准备国内大厂校招或社招,重点应该放在高频面试题和模板题上,追求覆盖面,因为面试手撕环境通常要求你在白板或在线IDE上写出完整代码,高频题必须练到条件反射。如果是准备算法竞赛,那力扣题单只是辅助,真正的主战场在洛谷、Codeforces这些OJ上,要适应读题、分类、优化复杂度、处理输入输出格式的完整流程。如果只是提升日常编码基本功,那数量更不重要,每周把一到两个专题吃透反而更好。

目标明确的另一个作用,是帮你做减法。网上的刷题资源太多了,力扣全站的题解就有成千上万篇,你的问题往往不是没题做,而是不知道该在哪里停下。代码随想录的公开题单本身就帮你精选过一轮,你不需要再额外打开十个收藏夹。我自己是面试党,所以只做了其中大约120道精选题,要求每道都能独立重写,这比我之前盲目做300道但大部分全忘光要实在得多。

2.2 一套能坚持三个月的节奏表

不要相信“七天刷完力扣”这类标题。真正能坚持下来的节奏必须容错率高、每天负担不重。我建议按三个月、每天1.5到2小时来排,每周一个专题,工作日学新题,周末统一复习。下面是我实际跑过的一周模板,可以直接抄:

时间段内容说明
周一到周五 19:00-19:30重做昨天做错的题必须关掉题解,先自己写
19:30-20:00做当天新题先独立思考至少15分钟
20:00-20:30对照题解重点看思路差异,先不看代码
20:30-21:00整理模板和复盘写入自己的笔记系统

这里最容易偷懒的是“独立思考15分钟”和“重做错题”。很多人卡在10分钟没思路就去看题解,看的时候觉得懂了,实际上只是“记忆懂”,不是“推理懂”。把独立思考时间放宽到15分钟,哪怕最后没做出来,你对题目的结构也会留下印象,再看题解效率会高很多。周末复习我建议采用“白纸重写”:不打开任何资料,把本周接触过的核心题在白纸上默写出来。写不出来就标记成重点题,下周再来一遍。这个方法很笨,但对抗遗忘的效果比再刷十道新题好太多。

2.3 复盘模板:让每道题都留下东西

做完一道题,别急着点下一道。我给自己定了一个记录模板,每次写题都按六项填:题目编号与名称、题目分类、一句话思路、时间与空间复杂度、卡住的点、我的模板代码。分类是重中之重,比如“滑动窗口+哈希计数”“二叉树递归+返回值收集”“动态规划+状态压缩”,这些标签以后会变成你检索思路的索引。卡住的点也要写具体,比如“没想到用哈希表存已经出现的值”,而不是只写“看了题解”四个字。

这些记录最终沉淀成两个本子:一个是模板本,放着每个专题的泛化代码,比如二分模板、链表反转模板、二叉树遍历模板;另一个是错题本,放着反复翻车的题。模板本最好不要从网上抄,而是你每次用题解思路重写之后总结出来的。为什么必须自己写?因为抄代码只会让你记住文本,自己总结才会让你记住决策。比如反转链表,关键不是那三行指针交换,而是先保存后继节点,否则链条就断了。这种决策只有在自己动手吃一次亏之后,才会真正刻进脑子里。

3. 实操记录:用这套方法连续啃下三道典型题

这一章我选三道有代表性的题,把实际刷题时“盯着一道题半小时”的完整过程还原出来。三道题分别对应数组、链表、动态规划三个核心专题,难度也是逐步上升的。

3.1 二分查找:用“循环不变量”根治边界问题

以力扣704二分查找为例。题目给一个升序数组和一个目标值,要求返回目标值下标,不存在则返回-1。很多初学者会先写暴力循环,但既然数组有序且要找特定值,考点就是二分。真正的难点不是“二分”这个概念,而是把边界写对:left和right在什么条件下相等?mid已经不在区间时怎么收缩?

我采用的模板是左闭右闭区间,也就是 left 和 right 分别指向当前查找区间的第一个和最后一个位置。初始时 left=0,right=nums.size()-1;循环条件用 left<=right,因为当 left==right 时,这个位置还没有被检查,不能跳出。mid 的计算用 left + (right-left)/2 而不是 (left+right)/2,是为了防止 int 溢出。下面是我按这套思路写出的完整代码:

int search(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; // 这里定义区间为左闭右闭 [left, right] while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) return mid; // 目标在右半边,左边界收缩 if (nums[mid] < target) left = mid + 1; // 目标在左半边,右边界收缩 else right = mid - 1; } return -1; }

逐行讲一下:当 nums[mid] < target 时,说明 mid 以及它左侧所有元素都不可能是答案,所以下一轮从 mid+1 开始找;反之当 nums[mid] > target 时,下一轮要找的是 [left, mid-1]。这里的核心是一个不变量:每一轮循环开始时,答案必然还在 [left, right] 内。只要这个区间定义不被破坏,循环退出时返回-1就是正确答案。这个思想能通吃搜索插入位置、查找左右边界、寻找峰值等一系列变体。我在刷到这组题的时候,把每个变体都按左闭右闭模板重写了一次,从此遇到二分题基本不再卡边界。

这里我要强调一个经验:二分不是背 while 里面是 < 还是 <=,而是在写代码前先声明你用的是“左闭右闭”还是“左闭右开”。区间定义一旦明确,所有边界都可以靠不变量推出来,而不是靠试错。这也是这套方法给我解决的第一个大痛点。

3.2 反转链表:画图比看十遍题解有用

第二个例子是力扣206反转链表。很多人的第一反应是遍历链表,把值存到数组,再逆序构造一条新链表。这个方法能做出来,但面试官看到基本会继续追问“能不能原地反转”,而且普通做法多了一次遍历和O(n)额外空间,显然不优。

原地反转的核心是三个指针:pre 指向前一个节点,cur 指向当前节点,tmp 用来保存当前节点的后继。为什么必须用 tmp?因为当你执行 cur->next = pre 时,cur 原来的后继就丢了,如果不先保存,下一轮就无法继续往前走。代码非常短,但第一次写的人十个里有七个会忘记保存后继。完整代码如下:

ListNode* reverseList(ListNode* head) { ListNode* pre = nullptr; ListNode* cur = head; while (cur != nullptr) { ListNode* tmp = cur->next; cur->next = pre; pre = cur; cur = tmp; } return pre; }

我强烈建议你盯着这段代码画一张图:画一条 1 2 3 4 5 的链表,把 pre 初始化成 null,cur 指向1,然后一步一步走,每走一步更新一次箭头。这个过程看起来枯燥,但能帮你在“指针操作”上建立空间记忆。有了这个画面之后,再做“反转链表的前N个节点”或“K个一组翻转链表”,你会觉得眼睛里有图,而不是靠背代码。递归版本也可以写,但我个人建议先用迭代法把指针流转吃透。递归版虽然代码短,但跳进去之后的栈帧变化对新手不友好,容易产生“反正递归调用一下就完了”的误区。把迭代和递归都写顺手之后,再看链表进阶题会发现,大部分难题的本质都是“找到要断开的节点→保存后继→切换指向→移动指针”,和这一题一模一样。

3.3 爬楼梯:动态规划五步法不是玄学

第三个例子是爬楼梯。题目很生活化:每次可以爬1阶或2阶,问到达第n阶有多少种方法。这是简单题,但它是很多人理解动态规划的第一道坎,也是代码随想录里反复强调“动态规划五步法”的首练题。

五步法分别是:确定dp数组的含义、找到递推公式、初始化、确定遍历顺序、打印dp数组验证。先看第一步,设 dp[i] 表示到达第 i 阶的方法数。第二步推公式,到达第 i 阶只可能是从 i-1 阶迈1步来的,或者从 i-2 阶迈2步来的,所以 dp[i] = dp[i-1] + dp[i-2]。第三步初始化,dp[1]=1,dp[2]=2。这里要注意,不要惯性写成 dp[0]=0,因为从0阶到2阶其实只有一种连续迈2步的方式,和题目语义容易混淆。第四步遍历顺序,因为递推依赖前面两个值,所以从3到n正序遍历。第五步,如果结果不对,把dp数组打印出来,逐一对比是不是每一步都符合推演。

这五步里新手最容易翻车的是第一步和第三步。dp数组含义定错,后面全错;初始值定错,算到后面会离正确答案越来越远。最终代码可以优化成两个滚动变量,不需要保留整个dp数组:

int climbStairs(int n) { if (n <= 2) return n; int prev = 1, cur = 2; for (int i = 3; i <= n; i++) { int next = prev + cur; prev = cur; cur = next; } return cur; }

为什么敢滚动?因为递推公式只依赖 i-1 和 i-2,前面的状态不会再被用到,空间复杂度就能从 O(n) 降到 O(1)。这个优化同样是从规则推导出来的,不是单纯的炫技。做完爬楼梯,再去做最小花费爬楼梯、不同路径、整数拆分,你会发现它们都共用同一套“定义dp、找递推、验遍历”的流程。动态规划看起来题型千变万化,但骨架就是这五步。只要遇到一道新题时能按步骤拆解,哪怕一时想不出公式,也知道自己卡在第几步。

4. 常见问题与排坑记录

4.1 卡在边界条件里出不来

边界条件几乎是刷题前期的头号杀手。我之前写二分时,反复在“到底什么时候 left=right+1”上翻车。后来找到的最有效方法,不是背结论,而是小数据模拟。写代码前先把空数组、单元素、双元素、目标在开头、目标在结尾这五类用例在纸上推演一遍。二分题写完代码,至少要测目标比最小值还小、比最大值还大的情况;链表反转要测空链表、单节点、两个节点;爬楼梯要测 n=1、n=2、n=3。这些最小用例加起来只要一分钟,却能在提交前挡住大部分边界错误。

另一个实用技巧是“调试输出”。很多人一遇到问题就断点调试,但在OJ的在线环境里,断点操作反而繁琐。直接在循环里打印 left、mid、right,或者打印dp数组,一眼就能看出来区间收缩不对。报错时别只盯着那一个失败用例,先把自己手算的小用例跑一遍,通常能更快定位问题。

4.2 看完题解就忘,第二天啥也不会

这是最多人问我的问题:看题解时觉得全会,关掉页面脑子一片空白。原因是大脑进入了被动接收模式,没有主动输出。解决方法只有一个:合上题解重写,把自己卡住的位置记成一句话。下面是我整理的排查速查表:

现象直接原因处理办法
看题解时觉得全会大脑被动接收,没有主动输出关掉代码只保留思路,重写一遍
重写时卡住没标出关键断链点复盘时写清卡点,下次先看卡点再动笔
过几天完全没印象缺少间隔重复按1天、3天、7天规律重做错题
同类型换成新题不会只背了代码没建模板抽象出一句话思路,再套到新题上

特别说最后一行。很多人觉得“明明做过相似的题,为什么换个条件还是不会”,原因是只记住了那个题的代码,没有抓住它背后的通用结构。比如你做了爬楼梯,记住了两个滚动变量,却没有抓住“最后一步从哪里来”的转移思想,那换成不同路径就无从下手。所以我坚持在复盘模板里加“一句话思路”这一栏,逼自己用自然语言描述解法,而不是直接贴代码。

4.3 进度焦虑与“刷题数量”迷信

刷题群里永远有人晒“今天第500题打卡”,心态很容易崩。我的判断标准从来不是题号,而是“能否闭卷写出核心模板”。代码随想录题单的题量不算大,但每道题重写三遍之后,你获得的是可以迁移的模型。从反转链表到K个一组翻转,从二分查找到搜索旋转排序数组,从爬楼梯到零钱兑换,这些迁移关系比“今天AC三道新题”更有价值。

如果已经陷入焦虑,建议先停掉那些贩卖焦虑的帖子,回到当前专题,把这一周碰过的所有题重写一遍。重写会带来很真实的正反馈:你看着昨天还不会的题今天能写出来,这种确定的进步比任何打卡数字都稳。还要学会接受“有些题第一次就是做不出来”,这不丢人。第一次做不出来、第二次能写出来,说明学习正在发生;第一次做不出来就放弃,才真的亏。

4.4 平台和语言选择避坑

平台选择上,力扣最贴近面试场景,中文题解丰富,适合大多数人;洛谷更重算法竞赛,题面、数据范围和输入输出格式都更硬核,适合想锻炼读题和输入处理的人;牛客上有大量笔试真题,适合已经进入投递阶段的人。不建议同时开五个平台,主力一个,其他当题解仓库看就够了。

编程语言方面,别因为网上题解大多是C++就临时切换语言。如果你平时用Python写业务,就用Python刷算法;如果你的目标岗位是C++后端,就多用C++练习指针、引用这些语法差异。刷题的核心是算法和数据结构,语言只是载体。Python写起来短,适合快速验证思路;C++更适合扣复杂度和内存模型。我见过用Python刷题很顺的人,面试时让他现场用C++写就露怯,根源是语言不熟,不是算法不熟。所以最好提前确认目标岗位常用语言,至少提前一个月切过去练。

最后再分享一个我自己坚持了很久的小习惯:每类题型都固定一组“最小测试用例”,存在本地。二分固定跑空数组、单元素、目标在开头、目标在结尾这四种;链表反转固定跑空链表、单节点、两个节点这三种;动态规划固定跑 n=1、n=2、n=3。每次写完代码,先把这几个用例跑一遍再提交,能规避至少一半的边界错误。这套刷题方法听起来不刺激,没有“30天速通”的爽感,但每一步复盘都能看见自己在进步。刷题这件事,最终比的不是谁见过的题多,而是谁能把见过的题变成自己的模型库。代码随想录给了我一个足够清晰的起点,剩下的路,需要你亲手走一遍。

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

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

立即咨询