LeetCode刷题核心:建立题感与高效刷题路线
2026/9/24 20:04:01 网站建设 项目流程

不用把LeetCode当成神坛上的东西,它本质上就是一套题库和在线评测系统。但你要是追过热搜、逛过讨论区,会发现围绕它的话题早就超出了"刷题"本身。LeetCode刷题指南、LeetCode简单题值不值得做、LeetCode热门100题到底该怎么用、周赛430打得稀碎怎么办,这些才是一个普通程序员真正关心的东西。我刷了几年,从一题都写不出来到稳定周赛三题,中间踩过不少坑,也总结了一些自己的方法。这篇东西不打算讲鸡汤,也不打算堆概念,就把我实际做题过程中的拆解思路、踩坑记录、以及一套可执行的刷题路线整理出来,希望对正在纠结"该从哪里下手"的人有点用。

1. 为什么说LeetCode刷题的核心不是"刷",而是建立题感

很多人把"刷题数量"当成唯一指标,好像刷到500题、1000题就自动变强了。但实际面试的时候,遇到没见过的题照样卡住。这里的问题不在于刷得不够多,而在于没有建立起"题感"。题感是个很玄的说法,但可以拆成三个具体能力:能识别这道题属于哪个解题套路、能判断最优解的方向、能在写代码之前大概估算出时间复杂度和边界条件。

1.1 简单题的价值被严重低估了

LeetCode简单题在很多人眼里是"入门水平",刷几道就跳过去了。但以我实际的经验来看,简单题才是建立题感的基石。简单题的考点往往非常单一,比如双指针、哈希表、基础遍历,它不会像中等题那样把多个技巧揉在一起。正因为单一,你才能清楚地看到"什么特征对应什么解法"。

举个例子,LeetCode热门前100题里,很多简单题反复在考同一件事:遍历数组时维护一个额外的数据结构。两数之和是哈希表、有效的括号是栈、合并两个有序链表是双指针。当你把这些简单题做熟,你会形成一种条件反射,看到"查找是否出现过"就想到哈希表,看到"括号匹配"就想到栈,看到"有序数组"就想到双指针或二分。

这种条件反射就是题感的核心。它不是天生的,而是通过刻意练习简单题建立的。

1.2 热门100题为什么"热门"

LeetCode热门100题不是官方钦定的,而是由所有用户的提交行为自然形成的。它的特点有两个:第一,考点覆盖了面试最高频的算法类型,比如链表操作、二叉树遍历、动态规划入门、BFS/DFS基础题;第二,这些题目的解法通常不止一种,而且每种解法的思路都能迁移到其他题目上。

我自己刷下来的感受是,热门100题适合用来做"专题训练"的目录。按标签分类,比如把所有链表题放一起刷,把所有岛屿类DFS/BFS放一起刷,把所有背包类DP放一起刷。你会发现同一种套路在不同题目里反复出现。比如BFS通常解决"最短步数""最少操作次数"问题,DFS通常解决"是否可达""路径是否存在"问题。这个区分一旦建立起来,遇到新题你至少能确定切入方向,而不是对着空白的编辑器发呆。

1.3 从"看题解"到"写题解"的转变

刷题圈有个普遍的坏习惯,就是五分钟没思路就点开题解,看完觉得"懂了",然后下一题。这种状态持续很久只能感动自己。因为看懂题解和能写出题解是两码事,前者是阅读,后者是输出。

我后来强迫自己做了两件事:第一,看完题解之后把代码关掉,自己重新写一遍,写不出来就再看再写,直到能不依靠任何参考独立写出来;第二,把题解用文字写下来,不要求长篇大论,但要说明白"为什么想到用这个算法""边界条件怎么处理"。

写题解的过程其实就是强化题感的过程。你是在强迫自己的大脑把"看懂了"的模糊感觉,转化成"能复述、能推理"的清晰结构。这个过程比多刷十道题有用得多。

2. 三道热搜题拆解:从"会做"到"会讲"

光说不练没有意义,拿几个典型的题目来拆一下。这里选的是最近热搜榜上常出现的三道:LeetCode 994腐烂的橘子、LeetCode 073爱吃香蕉的狒狒,以及链表类题目。这三道题恰好代表了三种最常见的解题范式:多源BFS、二分答案、链表双指针。

2.1 994腐烂的橘子:多源BFS是一层一层扩散的思维

题目是这样的:一个网格里,0代表空位,1代表新鲜橘子,2代表腐烂橘子,每个腐烂橘子每分钟会让上下左右相邻的新鲜橘子腐烂,问多久之后网格里没有新鲜橘子。如果不能全部腐烂,返回-1。

我第一次做这道题的时候有个误区:我对每个腐烂橘子单独做一次BFS,然后取所有腐烂橘子扩散到某个新鲜橘子的最短时间里的最大值。这样做能得到答案,但效率很差,而且代码写起来非常啰嗦。后来才发现,正确做法是多源BFS,把所有初始腐烂橘子同时当成BFS的起点。

多源BFS的核心逻辑是:初始化时把所有值为2的位置全部加入队列,然后统一进行层级遍历。每一层遍历代表经过了一分钟,层数就是结果。这里有个很容易踩的坑,就是"分钟数"到底从0开始还是从1开始。我的经验是,先把所有腐烂橘子入队,用一个变量记录队列中当前层的数量,然后按层处理。每处理完一层,分钟数加一。循环结束后检查网格里是否还有新鲜橘子,如果有就返回-1。

这道题的精髓在于"同时扩散"这个语义。例如两个烂橘子分别从不同方向逼近一个新鲜橘子,到达时间取决于距离更近的那个。如果分开做BFS,就得比较多个结果;一起做BFS,天然就是最先到达者取胜,这就和真实情况完全一致了。

复杂度方面,每个格子最多入队出队一次,所以时间复杂度是O(m * n),m和n是网格的宽高。这个解法思路清晰、代码简洁,是面试官最想看到的版本。

2.2 073爱吃香蕉的狒狒:二分答案的关键是找到单调性

这道题的表面设定很可爱:狒狒要在H小时内吃完N堆香蕉,每小时吃一堆,每堆只能吃一把,每把可以吃K根,问K的最小值是多少。实际上它是一个典型的"二分答案"问题,也是LeetCode里"最小可行速度"类题目的代表。

为什么可以用二分?因为吃香蕉的速度K和总耗时之间是单调的。K越大,耗时越短;K越小,耗时越长。二分答案的核心就是正向判断"如果速度是K,是否能在H小时内吃完",然后在速度的可能范围里二分搜索最小的K。

判断函数本身很简单:对每一堆香蕉,吃完它需要的时间是ceil(pile / K)也就是(pile + K - 1) / K。把所有时间加起来,如果小于等于H,那么K是可行的。问题在于很多人一开始想不到对速度做二分,而是习惯从1开始逐个尝试,这在数据量大的时候会超时。

这个题给我最大的启发是:当你发现题目要求的是"最小值""最大值""最短时间"这类词的时候,可以优先想一想是否存在单调关系。如果存在,二分答案通常就是那把钥匙。至于二分的边界,我习惯用左闭右开的写法,left = 1right = max(piles),然后while (left < right),这样写可以避免很多死循环的边界问题。判断函数放在二分循环里面,每次计算一个mid,然后判断是否可行,根据结果收缩区间。

2.3 链表类题目:dummy节点和双指针几乎能解决所有面试题

链表算是LeetCode里最"讲基本功"的题型了。它的代码量不大,但非常容易出错,因为牵扯到指针的移动和节点之间的断链重连。热门100题里链表题占了相当比重,反转链表、合并两个有序链表、环形链表、链表的中间节点,都是高频出的题。

我刷链表题踩过最大的坑就是:没有使用dummy节点,导致头部节点需要单独处理,代码写得又长又容易出bug。dummy节点的作用非常纯粹,它让链表的头节点和其他节点一视同仁,避免写if (head == null)这种分支。比如反转从位置m到n的链表,用dummy节点可以让你在操作头部区间的时候不需要额外讨论"如果从头开始反转怎么办"。

双指针对链表来说有两个常见的应用场景:快慢指针找中间节点或判断环,以及间隔指针用来删除倒数第N个节点。快慢指针的原理很简单,快指针一次走两步,慢指针一次走一步,如果链表有环,两者一定会在环内相遇。这个结论本身很直觉,但面试的时候需要能说清楚为什么——因为当快慢指针都进入环之后,快指针相对慢指针每次接近一步,所以一定能遇上。

我建议链表题不要只追求写出来,还要练习在纸上模拟指针的移动。面试时如果能在白板上画出每一步的指针变化,通过率会高很多。这个能力没有捷径,只有反复手写模拟。

3. 周赛430里的几个实战信号

周赛这个词经常上热搜,LeetCode周赛430也是最近的一次。很多人觉得自己没实力,不敢碰周赛,或者参加了之后被虐得体无完肤,然后陷入自我怀疑。但我认为周赛的价值不在于排名,而在于暴露问题。

3.1 周赛是很好的"短板诊断工具"

周赛的四道题通常是梯度难度:前两题偏热身,第三题中等偏难,第四题基本是竞赛级别。这意味着什么?它模拟了一个真实的竞技场景,让你在有限时间内快速判断每道题的难度、取舍策略和代码实现能力。

我参加周赛的体验是,做不出第四题很正常,但如果前两题花了太长时间,或者第二题写出了基本解法但没有优化到可以通过全部测试用例,这说明基础还不牢。周赛的好处就是逼着你在60到90分钟之内连续处理多个不同类型的问题,把所有弱点都摊开。等你回头看自己的提交记录,很容易发现"每次都在链表题上卡住"或者"一碰到动态规划就紧张"这类规律。

3.2 时间分配和跳跃式策略

周赛里有一个很重要的策略:遇到一道题看了五分钟没有明确思路,就立刻先跳过做后面的题。有很多人卡在一道题上死磕,最后导致后面的简单题时间不够,心态也崩了。这是非常不划算的。

我可以分享一个比较实用的分配方案:第一题做完尽量不要超过10分钟,第二题争取在20分钟内解决,第三题留25到35分钟,第四题能拿多少分算多少。这个方案不一定适合所有人,但它背后的逻辑是通用的——优先拿下稳定的分数,再挑战高分。第四题如果只剩10分钟,千万不要从零开始写代码,先看一下数据规模,如果暴力解法能过小数据就直接暴力,能拿到部分分数也是胜利。

3.3 如何正确地复盘周赛

周赛结束之后,复盘比参赛本身更重要。我一般会按照三个步骤来做。

第一步,把每道题重新做一遍,不看任何人的代码。做不出来就继续想,直到自己写出来为止。这个过程可能比正式比赛花的时间还长,但它能真正强迫你把思路理清。

第二步,去讨论区看别人的解法,但只看思路描述,不看完整代码。重点观察别人切入点和我有什么不同。比如一道题我用的是排序+贪心,别人用的是优先队列,那就要想一想为什么优先队列更优,在什么数据量下差异明显。

第三步,整理到自己的错题本里。错题本不抄全部代码,只记录三样东西:题目编号、我的思考方向、卡住的关键点。比如"看到需要维护动态最大值,第一反应是排序,但插入频繁导致超时,应该用堆"。这样一段时间之后,你的错题本实际上就是一份私人定制的刷题指南。

4. 我整理的个人刷题指南:从零基础到稳定AC

最后这部分是我自己花了不少时间总结的一套可执行的路线。不一定适合所有人,但它的框架是通用的,你可以根据自己的基础和时间调整。

4.1 第一阶段:打地基,只做专题,不做综合题

很多新人一上来就随机挑题做,今天一道数组题,明天一道树题,后天突然蹦出个动态规划。这种乱序刷法最大的问题是:你还没有形成任何套路储备,遇到一个需要多个知识点结合的题,完全无从下手。

我的建议是,前一个半月按专题刷,每个专题选10到20道题,从简单到中等梯度推进。推荐顺序是:数组和字符串 → 哈希表 → 双指针 → 链表 → 栈和队列 → 二叉树 → BFS/DFS → 二分查找 → 动态规划入门 → 贪心。

每个专题刷完,不用急着做难题,先确保自己能把该专题的基础题做得又快又稳。比如二分查找专题,把"在有序数组中查找目标值""查找第一个大于等于目标值的位置""查找最后一个小于等于目标值的位置"这三板斧练熟。后面遇到任何二分题目,判断函数可能会变,但二分框架本身不用重新学。

4.2 第二阶段:按"套路"归并,而不是按"题号"归并

基础专题过完之后,你会发现自己已经有了一定的题感。这个时候进入第二阶段:梳理套路。

常见的套路其实没那么多,翻来覆去就是这些:滑动窗口、前缀和、差分数组、单调栈、并查集、字典树、拓扑排序、最短路、背包DP、区间DP、状态压缩DP。每一个套路都对应一批经典题。

我自己的做法是建一个表格,列名是"套路名称、识别特征、经典题目、复杂度"。

套路识别特征经典题目
滑动窗口连续子数组、子串、最长/最短、窗口和无重复字符的最长子串,最小覆盖子串
前缀和连续子数组的和、区间查询和为K的子数组,区域和检索
单调栈找左右两边第一个更大/更小的元素每日温度,接雨水
并查集连通性、朋友圈、等价类省份数量,岛屿数量
BFS最短步数、最小操作次数、层序扩散腐烂的橘子,打开转盘锁
DFS搜索所有路径、判断可达性、组合枚举岛屿数量,子集

这个表格不需要一次性做完,而是在刷题过程中不断补充。每当你遇到一道可以用新套路解决的题,就把它写进去。等你积累了大概三十到五十个条目之后,你会发现新题大多都能在表格里找到相似的身影。

4.3 第三阶段:按热度刷,用周赛验证水平

第二阶段积累到一定程度之后,就可以进入第三阶段了。这个时候直接刷LeetCode热门100题,但目的不是追求做完,而是检验自己的套路储备够不够用。每一道题做的时候都要问自己三句话:这道题在考哪个套路?我第一时间想到了吗?为什么没想到?

如果三句话都能顺利回答且代码写出来通过了,说明这个知识点你已经掌握了。如果只是勉强做出来,那就把对应的专题再过一遍。如果做不出来,说明这个专题存在盲区,回到第二阶段去补。

周赛可以在这个阶段开始规律参加,不建议每周都用尽全力打满,但至少要保证每个月一到两次,用它来测试自己的临场状态。平时刷题可以通过的题,周赛高压环境下可能写不出,或者写出来了但超时,这些信号都非常宝贵。

4.4 常见误区:为什么你刷题很久却没有进步

一个扎心的观察是:大部分人在刷题这件事上的努力方式,其实是在用自己的舒适区反复消耗时间,而不是在突破学习区。具体表现为三个误区。

第一个误区是只刷自己会的题。很多人坐到电脑前习惯先选择"简单题",因为简单题短时间能出成就感。但如果你连简单题都要花很长时间,那问题不大;如果你大部分简单题做起来非常轻松,却还在刷简单题,那就是在浪费时间了。这个阶段的舒适区需要主动打破,把难度提升到"有点难,但想一想能解出来"的程度。

第二个误区是只看题解,不独立思考。独立思考并不等于死磕。我给自己定了一个规则:一道题十分钟没有头绪,可以看题解,但看完题解之后必须独立重写一遍,并且用文字记录这道题的关键思路。如果连重写都做不到,那说明根本没懂。

第三个误区是把AC当成终点。AC表示你的代码通过了测试用例,但不代表你理解了这道题的最优解法。最典型的就是暴力法过了,就不再考虑优化。在面试场景里,暴力解法通常只能拿到很基础的分数,面试官更希望你给出最优解法,并且能分析复杂度。

所以我非常推荐在AC之后再做一次"解法复盘":去讨论区看最高票回答,看完之后用这个思路重新写一遍。有些题我甚至会把四种不同做法都写一遍,比如同样是二叉树的层序遍历,分别用BFS队列、DFS递归维护层号、以及迭代方式实现。每种写法都会加深你对数据结构本身的理解。

4.5 关于刷题节奏和心态的几点体会

节奏方面,我比较推荐长期主义。每周至少刷四天,每天一道到两道题,周末可以集中做专题或参加周赛。一次刷十个小时然后一个月不碰,远不如每天稳定刷半小时。大脑对算法的熟悉感需要持续刺激来维持。

心态方面,不要把LeetCode的难度当成评价自己能力的唯一标准。会刷题不意味着所有工程问题都能解决,但通过刷题训练出来的抽象思维、边界条件意识和代码处理能力,确实会反馈到日常开发里。比如处理复杂的状态流转、并发条件下的竞态、或者接口参数校验的时候,你会更自然地想到边界情况。

我自己的一个习惯是,手机备忘录里建了一个"解题灵感"列表。平时看文章、逛论坛、甚至走在路上想到某个算法问题的变体,就顺手记一笔。比如看到外卖配送路径规划,会想到BFS与Dijkstra的使用边界;看到优惠券凑单,会想到多个槽位的DP还是背包。这种把题目和现实连接起来的练习,会让刷题变得不那么枯燥,而且记忆更深刻。

最后再分享一个小技巧:做题时把函数名和参数名写得更语义化。虽然LeetCode的评测只看逻辑正确性,但一个好的命名习惯能让你在面试环境中更快地理清思路。我会把BFS里的队列变量命名成queuecurrentLayer,把动态规划的DP表命名成dp加注释说明含义。代码是写给未来的自己看的,这一点在刷题阶段就养成,后面会受益很多。

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

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

立即咨询