首页 / 资讯中心 / 文章详情

从刷题小白到稳定输出:LeetCode高效刷题方法论与核心题型拆解

从刷题小白到稳定输出:LeetCode高效刷题方法论与核心题型拆解 ★ FEATURED ARTICLE
我刷了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-23所以核心问题变成怎么在被减号影响的情况下正确决定当前数字最终是加还是减。我的解题模板是维护一个符号栈或者一个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里合作intJava里IntegerPython里无此烦恼但如果用C就必须考虑。递归时有没有考虑递归深度二叉树退化成链表时深度可能等于节点数Python和Java默认递归栈不够用时会栈溢出。我的一个强制习惯是写完代码之后先不急着提交手动拿三个用例去跑一遍逻辑。第一个是题目给的示例第二个是边界用例空数组、单元素、极值第三个是反例如果题目要求输出-1你得构造一个让你输出-1的场景。这三步能拦下大部分低级错误。很多人根本没这步就死磕提交被AC率教做人了。5.2 超时问题的常见原因与优化方向TLE是所有刷题人的心头恨。常见的超时原因有几类一是复杂度爆炸比如DFS做了指数级搜索应该用DP二是重复计算比如递归里没有记忆化同样的子问题算了一万遍三是可以用双指针或滑动窗口的地方用了嵌套循环。排查顺序我建议这样先看数据范围。如果数组长度是10^5O(n²)肯定是超时的那你一开始就别写嵌套循环。如果长度只有10³那O(n²)可能没问题别一上来就上什么高级数据结构写复杂了反而容易出Bug。然后优化的方向按这个优先级暴力 → 哈希表优化查找 → 双指针/滑动窗口 → 排序 → 二分 → 前缀和/差分 → 单调栈 → DP → 图算法。每上一级都要想清楚代价空间是否增加实现复杂度是否可控边界是否更难处理优化的本质是权衡不是越复杂越好。5.3 好记性不如烂笔头建立自己的错题本错题本这个东西学生时代觉得没意思工作了反而觉得是真香。我的错题本不是简单抄题目和答案而是每条记录包含五个要素题目链接、错误原因、正确思路、类似题目、下次遇到这类题我该第一时间想到什么。这样做的核心意义是你在强迫自己“提炼信号”而不是“存储噪声”。举个例子我第一次做基本计算器的时候错误原因是“忽略了括号前的负号会翻转内部所有符号”我在错题本上记下之后又找了三道带括号的表达式题来验证这个认知。这个错题本现在已经有500多条记录平时没事翻一翻很多面试题考的都是里面记录过的“老朋友”。5.4 新手最容易陷入的四个误区最后总结一下新手期我见过最多的四个误区也贴一下我自己的踩坑经历。第一个误区是“只做新题不做旧题”。我见过有人刷题数量400但回访率极低问他上周做过的一道Medium他说有点印象但忘了怎么做。这种刷法数量是给别人看的不是给自己长实力的。我强制自己做旧题每周至少15道复习旧题才把知识网织起来。第二个误区是“死磕Hard题”。Hard题往往组合了多个难点如果你连它的前置范式都没掌握死磕就是浪费时间。我自己的节奏是Easy和Medium的比例大约3:7Hard只在周赛复盘和后续补题时碰。不是说Hard没用而是要把Hard放在自己能力边缘练起来才有增长效果而不是放在能力范围之外那叫受虐。第三个误区是“不审题就开始写”。LeetCode有时候题干很长尤其是模拟类的题很多关键限制藏在最后一段话里。我吃过一个大亏有一道题看起来是求最大路径和我以为直接贪心结果原来是对顺序有要求必须拓扑排序处理。那次TLE教我学会了写代码之前先花两分钟把题目的输入范围、输出要求、限制条件圈出来。第四个误区是“不重视代码风格”。Contest里有人代码写得像天书变量名全是a、b、c嵌套三层for自己事后都看不懂。面试官看代码时是在判断你未来的工程协作能力所以变量命名要有语义复杂逻辑要加注释提交之前顺手把冗余分支理干净。这些习惯会在面试里为你加分也会让你自己的复盘痛苦程度大幅降低。6. 给不同阶段的刷题者的一些实在建议6.1 如果你是零基础先把“数据结构”课补上我见过不少零基础的人直接上来刷LeetCode然后迅速被劝退。原因是很多题默认你熟悉“哈希表”“栈”“队列”“二叉树”这些基本概念。零基础的人最需要的不是刷题而是先花两到三周的时间把常用数据结构的概念和基本操作搞明白。资源方面不必贪多选择一本评价好的数据结构书或者一门口碑好的网课就足够了。重点是能说清“数组和链表的区别”“栈和队列分别适合什么场景”“树和图的遍历方式”“哈希表是如何做到O(1)查找的”。这些基础不牢刷题就像没打地基就盖楼越刷越塌。等数据结构基础扎稳再进入LeetCode每天保持两道题的节奏第一遍不求数量只求每道题都弄明白为什么这么做。第一个月你会觉得慢但坚持到第三个月你会发现自己的速度有了质变。这其实是所有技能学习的正常曲线前期慢后期快熬过平台期是关键。6.2 如果你有一定基础用“复述法”检验真懂很多刷了大几十题的人最尴尬的状态是“看到答案能懂自己做不出来”。这里推荐一个我认为效率极高的方法——复述法。所谓复述就是做完一道题之后合上代码用自然语言向一个不存在的听众完整讲述这道题的思路这题在考什么为什么用这个算法边界有哪些坑。如果你能流畅地讲出来你是真懂了如果你磕磕绊绊讲着讲着发现自己说不清某一步那这里就是理解的漏洞所在。这个方法我也用在工作场景里。向同事解释一个系统设计方案时能讲清楚原理的人才是真正掌握它的人。刷题也一样复述不出来说明你脑子里存的是碎片不是结构。6.3 关于“刷题心态”的一点毒鸡汤最后想说点掏心窝的话。刷题这件事本质上是一个延迟满足的长期投资。你今天刷的三道题大概率不会在明天的工作里立刻见效它们的效果是两个月后、半年后、甚至下一次跳槽面试时才体现出来的。这种滞后性是很多人中途放弃的根本原因——“我刷了这么久怎么感觉什么也没变”我自己的经验是把刷题当成一个“储蓄账户”每天往里存一点别每天看余额看年度账单的时候你会惊喜的。还有一个缓解焦虑的方法是别跟别人比题数也别混进什么“百题速通”的群里天天看别人秀打卡。节奏是自己的题目数量是假的掌握度才是真的。如果你能坚持三个月每天保质保量完成一道题加一次错题复盘你再来回看今天的自己一定会感谢这段“日拱一卒”的时光。我个人这几年的体会是LeetCode这个东西跳出来看其实就是一套训练算法思维的系统。它的价值不在于那个排名也不在于那些小徽章而在于你被迫反复思考“为什么这样更快”“还有没有更优解”的过程。这个过程练出来的东西是实打实解决问题的能力它不只在面试中帮你在工作里遇到那些没有标准答案的问题时你会发现当年刷题时练出的思路已经长成你思维习惯的一部分了。如果你现在正觉得刷题痛苦不用怀疑那是你在打破舒适区的正常反应挺过去那段时间就顺了。
阅读完成 · 觉得有帮助?
咨询建站