☰
从刷题小白到稳定输出:LeetCode高效刷题方法论与核心题型拆解
2026/10/12 17:33:31 网站建设 项目流程

我刷了600多道LeetCode,参加过几十场周赛,从刚开始看到Medium就腿软,到后来能稳定做出四题里的三题,中间踩过的坑比写过的Bug还多。这篇不是题解合集,也不是什么“七天速通”的鸡汤,就是把我自己从刷题小白到能稳定输出的过程中,那些真正起作用的思路、方法、教训,一次性整理出来。里面会拆解几个典型题目的核心思维,比如最近热门的994腐烂的橘子、073爱吃香蕉的狒狒,还有那个让无数人头疼的基本计算器,也会聊聊周赛430的真实体验。如果你正在跟LeetCode死磕,或者刷了几十题但总觉得没长进,这篇应该能帮你看清楚问题出在哪。

1. 刷题这件事,先想明白再动手

1.1 大多数人的刷题方式,其实是在自我安慰

很多人打开LeetCode,上来就按题号刷,今天做两道Easy,明天看两道Medium的题解,收藏夹里存了一堆“待复习”,结果一个月过去,会的还是原来那几道。这不是笨,而是把“看过答案”当成了“会做”。我早期也这样,一度刷了150多题,自我感觉良好,结果面试官出一道二叉树层序遍历的变种,我愣是卡了十分钟才想起来BFS怎么写。

后来我想明白一个事:LeetCode的核心不是“刷”字,而是“练”字。它考察的是你把问题抽象成数据结构与算法模型的能力,而不是你见过多少道题。一道题做对了,你要能说清楚为什么想到用这个解法;换一个场景,你能不能认出它是同一类问题。这才是刷题真正的复利所在。

1.2 明确目标:你为什么要刷LeetCode

目标不同,打法完全不同。如果你是为了应付三个月后的面试,那重点是把Hot 100里的高频题吃透,每种题型能默写模板,时间应该花在“反复做旧题”上,而不是拼命开新题。如果你是为了打周赛、冲排名,那除了速度,还要刻意训练自己读题后十分钟内锁定算法方向的能力。如果你是为了提升工程中的算法敏感度,那就不能只刷题,得配合一些系统设计的思考。

我见过太多人目标混乱:明明下个月面试,还在周赛里为了排名死磕一道Hard,结果面挂了。刷题这件事,效率最高的状态是“带着明确的目的去练”,而不是“为了刷而刷”。我自己后来的节奏是:面试前三个月,每天两道Hot 100里的题,每道题至少写两遍,第二遍是隔天默写;平时不打比赛的日子,就做一到两道新题保持手感。

1.3 选择合适的刷题顺序和路线

LeetCode题号并不是难度顺序,跟着题号刷的人多半会夭折在早期。我比较推荐按“数据结构与算法专题”来刷,比如先过一遍“数组与字符串”,再来“哈希表”,然后是“双指针”、“链表”、“栈与队列”、“二叉树”、“回溯”,最后才是“动态规划”和“图论”。这样每学一个数据结构,就把它所有常见题型打透,形成条件反射。

另外一个重要的路线选择是“热门100题”。热词里有“leetcode热门100题”,我强烈建议把它当作主线任务。这100题是LeetCode官方根据考察频率和经典程度筛出来的,覆盖面很全。我的经验是:把这100题全部做到“看到题就能秒想思路+10分钟内写对”,再去刷别的题,性价比是最高的一条路。很多人说“我刷了500题还怕面试”,说实话,如果500题里不包括这100题的深刻理解,那500题可能真的不如别人把100题刷五遍。

2. 核心题型的拆解:Hot 100里的必会思维

2.1 993/994柑橘腐烂类问题:BFS的分层与多源思想

热词里有“leetcode 994 腐烂的橘子”,这个题很典型。它说的是一个网格里有新鲜的橙子和腐烂的橙子,腐烂的橙子每分钟会让上下左右相邻的新鲜橙子变烂,问多久全部腐烂,或者永远不可能。

这个题的核心是BFS的“多源+分层”思想。所谓多源,就是初始状态可能不止一个腐烂的橙子,所以起始要把所有烂橘子全部入队;所谓分层,就是每一轮扩散算一分钟,这对应BFS的层序遍历。很多人的误区是:用DFS去递归,结果层数很难控制,或者用两个循环嵌套来模拟每一轮,但那样写出来的时间复杂度容易变成O(n²m²),直接TLE。

我的建议是直接用队列做。伪代码思路大致是:先遍历一遍网格,把所有腐烂的橙子入队,同时统计新鲜橙子数量。然后进行BFS,每一轮把当前队列里的所有节点取出,向四个方向扩散,如果遇到新鲜橙子就把它变烂入队,新鲜橙子数量减一。最后检查新鲜橙子数量,如果不为零说明有橙子永远烂不了,返回-1;否则返回扩散了多少轮。

关键细节有两个:一是轮数的计数方式,很多人在BFS里用一个时间戳数组或者单独记录队列的大小,我习惯在每一轮开始前用int size = queue.size()固定本轮要处理的节点数,这样就能准确分轮。二是边界条件,数组为空、没有烂橘子但也没有新鲜橙子、输出是0分钟的情况。这个题本质上是多源最短路径问题的一种应用,理解了它,像“地图分析”“01矩阵”这些题就都通了。

2.2 爱吃香蕉的狒狒:二分答案的经典场景

“073爱吃香蕉的狒狒”这题,看起来是个模拟场景,实际上考的是二分答案。题目大概是说有一堆香蕉,每个小时吃一堆,吃不完就留着下一小时,给你一个速度K,问最小K能在H小时内吃完所有香蕉。

一眼看过去很多人想从1开始一个个试K,但数据范围一大就超时。正确的打开方式是:答案K一定在某个范围内,下界是1,上界是最大一堆香蕉的数量(因为速度再快,一小时也只能吃一堆)。然后在这个范围内二分查找:对于每一个中间速度mid,算出以这个速度吃完全部香蕉需要多少小时,如果小于等于H,说明速度可能还能再慢一点,就把右边界缩小;否则说明速度不够,把左边界扩大。

这个题最经典的坑是向上取整的写法。计算一堆香蕉在速度K下需要的小时数,应该是(pile + K - 1) / K,而不是简单的pile / K。很多人在这个细节上栽跟头,因为如果恰好整除,直接除没问题,但余数部分会导致少算一个小时。还有一个点是:理解“每小时只能吃一堆”这个限制,很多人算法写对了但理解错题意,以为可以同时吃好几堆,那就完全不一样了。

二分答案是LeetCode里一个非常大的题型家族。凡是求“最小值中满足条件的”或者“最大值中不满足条件的”,大概率都可以往二分答案上靠。狒狒吃香蕉这个题,长期以来一直是二分答案题型的入门必刷题,原因是它没有复杂的数学建模,题目描述又生动,拿来练“二分边界怎么处理”特别合适。

2.3 基本计算器:栈与状态机的实战检验

“基本计算器”这个题在热词里也出现了。这个题LeetCode上有无括号版、有括号版、加减乘除版,基础版是“实现一个支持加减和括号的计算器”。说实话这是栈相关题目里难度拉满的一道,因为它不仅考栈,还考状态解析。

为什么难?因为表达式是一个字符串,你得自己处理数字的拼接、运算符的优先级、括号引起的符号翻转。比如"1-(2-3)",展开来看其实等价于1-2+3,所以核心问题变成:怎么在被减号影响的情况下,正确决定当前数字最终是加还是减。

我的解题模板是维护一个符号栈或者一个sign变量。具体做法是:用一个栈记录当前括号层级外的符号状态;遍历字符串时,遇到数字就把连续的数字拼成一个完整的数,用当前的sign乘以这个数累加到结果里;遇到+或-就更新当前位置的符号;遇到(就把当前符号压栈,遇到)就弹栈。这样能正确处理括号嵌套。这个题的另一个难点是处理空格,我见过好几个同事面试时挂在空格上去除上,字符串里到处是空格结果解析数字的时候出错。

这个题我觉得最值得深思的一点是:它把“人工计算”的习惯思维带到了代码里。人肉算带括号的表达式时,会先算内层括号,但计算机不一样,用栈可以把括号当成符号翻转处理,效率更高。理解了这一点,不只是会做这一道题,什么四则运算计算器、逆波兰表达式求值、带有变量的表达式解析,思路都是相通的。

3. 从“看题解就懂”到“自己能写出来”

3.1 我为什么反对“刷题五分钟,看题解两小时”

这是很多人的真实状态:题目拿出来看了五分钟,没思路,于是点开题解。看完之后“哦原来是这样”,然后觉得自己会了。但到第二天再做一遍,还是写不出来。这个循环的根源在于:看题解时大脑产生的是“识别感”,而不是“调用能力”。这就像你看了别人弹吉他觉得自己也会了,但手指根本没有肌肉记忆。

我的做法是强制自己“先想后看”。一道题至少独立想30分钟。如果30分钟完全没有任何思路,才允许看题解,但看题解时只允许看解法的大标题,比如“用BFS”“用单调栈”,然后合上答案自己继续写。很多时候,知道方向之后,细节自己就能憋出来了。这一步看着简单,但它是区分“刷过题”和“会做题”的分水岭。

另外一个非常有效的习惯是:同一道题至少做三遍。第一遍独立完成,第二遍隔两三天重新做一遍,第三遍是隔一周直接用笔在纸上写,连代码都不要打。这个方法看起来费时间,实际上对长期记忆的保留效果,比做十道新题都强。Hot 100里的经典题,我基本都保持了这种三轮法。

3.2 写题的时候,先想“暴力”再想“优化”

很多人一上来就想着“最优解”。这个毛病我有过,后来改掉了。最优解不是想出来的,是分析出来的。正确路径是:先确认暴力解法可行——通常是模拟、直接枚举或递归——把它写对。然后在暴力解法的瓶颈处思考:哪里重复计算了?哪里可以缓存?是不是有单调性可以利用?

举个例子,狒狒吃香蕉那道题,暴力解法就是从1开始枚举速度,逐个验证,如果超时,你就会自然意识到“速度之间有单调性,验证结果随速度增加而从超时变为不超时,所以可以二分”。这个过程比一上来背二分模板要合理得多,因为你理解了模板背后的出发点。

在面试现场也一样。面试官不会因为你一开始没给出最优解就挂你,他考察的是你的思考推演过程。你从暴力到优化的这个过程,恰恰是表达你思维质量的机会。我面过不少候选人,直接上来背最优解模板,漏洞百出,反而不如一步一步从暴力推到优化的来得让人信服。

3.3 从题目抽象出范式:一类题一套代码

刷到一个量级之后,你会发现LeetCode考的其实就是那二三十种范式:二分答案、双指针滑动窗口、BFS/DFS、回溯、动态规划(背包/区间/线性)、单调栈、字典树、拓扑排序、并查集、最短路……每个范式都有“万金油模板”。

我自己有一个专门用来默写模板的习惯。在本地维护一个templates/文件夹,每种范式保存一个核心模板文件。比如BFS保存一个矩阵遍历模板,二分答案保存一个check(mid)模板,回溯保存一个“剪枝+路径记录”的模板。每次写题之前,先在脑海里过一遍模板,然后往里面填业务逻辑。这样不仅能提速,还能帮助保持代码风格一致,错误率会下降不少。

这里要多说一句:模板不是死记硬背的东西,而是你在亲手写过十道同类题之后,自然积累出的“最佳写法”。如果你还没写过足够多的同类题就去背别人的模板,很容易出现“模板是模板,题是题”的断裂感。所以更好的顺序是先刷十道题,再做模板,再带着模板去刷下一个十道。

4. 周赛430:真实比赛里暴露的真相

4.1 周赛到底在考什么

热词里有“leetcode周赛430”,说明这个关键词最近热度不低。周赛和平时刷题最大的区别是:时间被压到了极致,四道题,一个半小时,从读题到提交,你都要像在面试白板上一样思考。平时刷题你可以想一小时,周赛不行,想十分钟还没思路,基本就可以先跳下一题了。

我参加过不少场周赛,感受最深的一点是:周赛的题通常比Hot 100里的题更新颖,但底层范式不变。比如周赛第一、二题,基本就是签到题,考察的是你能不能快速读题、快速写代码、避免低级错误;第三题开始,就是拼你平时积累的范式熟练度了;第四题则往往需要你在一道综合题里组合两种以上算法。

周赛430那场我印象比较深,那场的第一题明显是一个简单的贪心或者排序,第二题是前缀和,第三题涉及图论里的BFS分层扩展,第四题是动态规划的状态压缩。我当时第二题在边界取模上卡了一阵,结果排名掉得很厉害。事后复盘,模运算的坑在LeetCode里太常见了,尤其是问“方案数”的时候,任何一步减法都可能变成负数,导致取模结果不对。这种细节平时刷题也能碰到,但在周赛的时间压力下,人更容易踩中。

4.2 我的周赛复盘方法

周赛结束之后,最重要的不是看排名,而是把四道题重新做一遍,并且在每道题旁边写上:这道题的突破口是什么?我卡在哪一步?哪个知识点是我临场想不起来的?这样做三场比赛下来,你会很清楚自己的薄弱带在哪里。

以我自己为例,我复盘了连续十场周赛之后,发现自己第四题总是卡在“状态定义”上,经常是看了一眼答案觉得状态设计很巧妙,但自己想不出来。后来我专门花了三周时间集中刷DP题,从线性DP到背包再到状压,每一道都按“三步法”——定义状态、转移方程、边界条件——刻意思考。再打周赛时,第四题的成功率明显上来了。

还有一个小技巧:周赛的题解可以晚一天看,别比赛一结束就急着看题解。因为赛后当天脑子里还是题目,你想一个晚上,第二天再来看题解,收获会大很多。这个习惯让我对很多题的理解深度明显区别于“当场看题解”的人。

4.3 怎么稳定提升周赛三题

想稳定做出周赛前三题,我的建议集中在两点:一是限时训练,每次周赛前的周中用一些中等难度的旧题,给自己15分钟,做不出来就下一题,训练紧迫感下的快速思考能力。二是保持赛后补题但限制时间,周赛第三、四题分别给自己20分钟和40分钟,时间到了再去看题解。

另外,建议参加双周赛的同时,把比赛时间当作真面试训练。开赛前把水杯、计算纸都准备好,过程中不开任何参考代码,不发消息。这种仪式感能有效让你进入比赛模式。一旦适应了这种节奏,你上真面试场的时候,对“白板写代码”这件事的恐惧会低很多。

5. 刷题过程中的常见问题与避坑指南

5.1 边界条件:90%的错误都发生在这里

我遇到的绝大多数“看了半天代码没错,一发就错”的情况,都源于边界条件。LeetCode的坑主要集中在这些地方:

  • 数组长度为0或1时,你的循环逻辑是否成立?
  • 二分查找时,left和right的初始值会不会覆盖所有可能答案?mid更新时会不会死循环?
  • BFS/DFS中,访问过的节点有没有在入队/递归的第一时间标记,防止重复入队?
  • 数字计算中涉及加减乘除时,会不会溢出?LeetCode在C++里合作int,Java里Integer,Python里无此烦恼,但如果用C++就必须考虑。
  • 递归时有没有考虑递归深度?二叉树退化成链表时,深度可能等于节点数,Python和Java默认递归栈不够用时会栈溢出。

我的一个强制习惯是:写完代码之后,先不急着提交,手动拿三个用例去跑一遍逻辑。第一个是题目给的示例,第二个是边界用例(空数组、单元素、极值),第三个是反例(如果题目要求输出-1,你得构造一个让你输出-1的场景)。这三步能拦下大部分低级错误。很多人根本没这步就死磕提交,被AC率教做人了。

5.2 超时问题的常见原因与优化方向

TLE是所有刷题人的心头恨。常见的超时原因有几类:一是复杂度爆炸,比如DFS做了指数级搜索,应该用DP;二是重复计算,比如递归里没有记忆化,同样的子问题算了一万遍;三是可以用双指针或滑动窗口的地方用了嵌套循环。

排查顺序我建议这样:先看数据范围。如果数组长度是10^5,O(n²)肯定是超时的,那你一开始就别写嵌套循环。如果长度只有10³,那O(n²)可能没问题,别一上来就上什么高级数据结构,写复杂了反而容易出Bug。

然后优化的方向按这个优先级:暴力 → 哈希表优化查找 → 双指针/滑动窗口 → 排序 → 二分 → 前缀和/差分 → 单调栈 → DP → 图算法。每上一级,都要想清楚代价:空间是否增加?实现复杂度是否可控?边界是否更难处理?优化的本质是权衡,不是越复杂越好。

5.3 好记性不如烂笔头:建立自己的错题本

错题本这个东西,学生时代觉得没意思,工作了反而觉得是真香。我的错题本不是简单抄题目和答案,而是每条记录包含五个要素:题目链接、错误原因、正确思路、类似题目、下次遇到这类题我该第一时间想到什么。这样做的核心意义是:你在强迫自己“提炼信号”,而不是“存储噪声”。

举个例子,我第一次做基本计算器的时候,错误原因是“忽略了括号前的负号会翻转内部所有符号”,我在错题本上记下之后,又找了三道带括号的表达式题来验证这个认知。这个错题本现在已经有500多条记录,平时没事翻一翻,很多面试题考的都是里面记录过的“老朋友”。

5.4 新手最容易陷入的四个误区

最后总结一下新手期我见过最多的四个误区,也贴一下我自己的踩坑经历。

第一个误区是“只做新题不做旧题”。我见过有人刷题数量400+,但回访率极低,问他上周做过的一道Medium,他说有点印象但忘了怎么做。这种刷法,数量是给别人看的,不是给自己长实力的。我强制自己做旧题,每周至少15道复习旧题,才把知识网织起来。

第二个误区是“死磕Hard题”。Hard题往往组合了多个难点,如果你连它的前置范式都没掌握,死磕就是浪费时间。我自己的节奏是:Easy和Medium的比例大约3:7,Hard只在周赛复盘和后续补题时碰。不是说Hard没用,而是要把Hard放在自己能力边缘,练起来才有增长效果,而不是放在能力范围之外,那叫受虐。

第三个误区是“不审题就开始写”。LeetCode有时候题干很长,尤其是模拟类的题,很多关键限制藏在最后一段话里。我吃过一个大亏,有一道题看起来是求最大路径和,我以为直接贪心,结果原来是对顺序有要求,必须拓扑排序处理。那次TLE教我学会了:写代码之前,先花两分钟把题目的输入范围、输出要求、限制条件圈出来。

第四个误区是“不重视代码风格”。Contest里有人代码写得像天书,变量名全是a、b、c,嵌套三层for,自己事后都看不懂。面试官看代码时,是在判断你未来的工程协作能力,所以变量命名要有语义,复杂逻辑要加注释,提交之前顺手把冗余分支理干净。这些习惯会在面试里为你加分,也会让你自己的复盘痛苦程度大幅降低。

6. 给不同阶段的刷题者的一些实在建议

6.1 如果你是零基础:先把“数据结构”课补上

我见过不少零基础的人直接上来刷LeetCode,然后迅速被劝退。原因是很多题默认你熟悉“哈希表”“栈”“队列”“二叉树”这些基本概念。零基础的人最需要的不是刷题,而是先花两到三周的时间,把常用数据结构的概念和基本操作搞明白。

资源方面不必贪多,选择一本评价好的数据结构书,或者一门口碑好的网课就足够了。重点是能说清“数组和链表的区别”“栈和队列分别适合什么场景”“树和图的遍历方式”“哈希表是如何做到O(1)查找的”。这些基础不牢,刷题就像没打地基就盖楼,越刷越塌。

等数据结构基础扎稳,再进入LeetCode,每天保持两道题的节奏,第一遍不求数量,只求每道题都弄明白为什么这么做。第一个月你会觉得慢,但坚持到第三个月,你会发现自己的速度有了质变。这其实是所有技能学习的正常曲线,前期慢,后期快,熬过平台期是关键。

6.2 如果你有一定基础:用“复述法”检验真懂

很多刷了大几十题的人,最尴尬的状态是“看到答案能懂,自己做不出来”。这里推荐一个我认为效率极高的方法——复述法。所谓复述,就是做完一道题之后,合上代码,用自然语言向一个不存在的听众,完整讲述这道题的思路:这题在考什么,为什么用这个算法,边界有哪些坑。如果你能流畅地讲出来,你是真懂了;如果你磕磕绊绊,讲着讲着发现自己说不清某一步,那这里就是理解的漏洞所在。

这个方法我也用在工作场景里。向同事解释一个系统设计方案时,能讲清楚原理的人,才是真正掌握它的人。刷题也一样,复述不出来,说明你脑子里存的是碎片,不是结构。

6.3 关于“刷题心态”的一点毒鸡汤

最后想说点掏心窝的话。刷题这件事,本质上是一个延迟满足的长期投资。你今天刷的三道题,大概率不会在明天的工作里立刻见效,它们的效果是两个月后、半年后、甚至下一次跳槽面试时才体现出来的。这种滞后性,是很多人中途放弃的根本原因——“我刷了这么久,怎么感觉什么也没变?”

我自己的经验是:把刷题当成一个“储蓄账户”,每天往里存一点,别每天看余额,看年度账单的时候你会惊喜的。还有一个缓解焦虑的方法是:别跟别人比题数,也别混进什么“百题速通”的群里天天看别人秀打卡。节奏是自己的,题目数量是假的,掌握度才是真的。

如果你能坚持三个月,每天保质保量完成一道题加一次错题复盘,你再来回看今天的自己,一定会感谢这段“日拱一卒”的时光。


我个人这几年的体会是,LeetCode这个东西,跳出来看,其实就是一套训练算法思维的系统。它的价值不在于那个排名,也不在于那些小徽章,而在于你被迫反复思考“为什么这样更快”“还有没有更优解”的过程。这个过程练出来的东西,是实打实解决问题的能力,它不只在面试中帮你,在工作里遇到那些没有标准答案的问题时,你会发现当年刷题时练出的思路,已经长成你思维习惯的一部分了。如果你现在正觉得刷题痛苦,不用怀疑,那是你在打破舒适区的正常反应,挺过去那段时间,就顺了。

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

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

立即咨询