
刷到第60天正好是1月19号这天。LeetCode面试经典150题单我从大概11月底开始啃中途断断续续、反复回退今天终于把这150题完整过完第一遍。说“过完”不是说每道题都能一遍秒杀而是所有题都至少动手写过、整理解过思路、记录了错误点。这份题单在准备技术面试的人里几乎人手一份但它到底适合谁、该用什么顺序刷、卡住了怎么处理真正说得清楚的并不多。这篇文章就把我60天的实际过程拆开来讲希望能给正在刷题或准备开始的人一点参考。1. 为什么是“面试经典150”而不是其他题单1.1 这份题单和其他题库的区别市面上的刷题资源无非几类按知识点分类的专项练习、公司高频题汇总、竞赛真题还有LeetCode官方出的面试经典题单。我一开始也纠结过到底刷哪个后来选了“面试经典150”核心原因是它的分类结构最适合面试场景。这份题单把150道题按知识点切成块数组/字符串、双指针、滑动窗口、矩阵、哈希表、区间、栈、链表、树、二叉树、图、回溯、分治、Kadane算法、二分查找、堆、位运算、数学、动态规划。注意它把树和二叉树分开列动态规划放在最后面说明官方是从面试出题频率和认知难度两个维度排的。相比之下“热题100”更偏高频但题目之间没有清晰的训练主线刷完容易“见一道会一道换一道就懵”。“面试经典150”更像一套教材每个知识点给足典型题刷完能自然建立解题框架。我个人的判断是时间紧张、只剩两周突击面试的人先去刷高频题更划算但如果是还有一两个月准备时间想把算法基础真正补到能应对大多数面试题的水平150题是最合适的性价比选择。1.2 60天的进度安排和阶段划分一天刷2到3道题加上复盘大概需要两个小时。这是比较稳的节奏。我见过有人一天刷10道但那样基本是看题解背代码过几天全忘。我的60天大致分成三个阶段前15天主攻数组、字符串、双指针、滑动窗口、矩阵、哈希表。这类题是算法题里的“基础代谢”几乎每场面试都会碰到而且很多复杂题的本质就是“数组哈希”的组合。中间25天主攻链表、树、二叉树、图、回溯。树和图是面试官最爱的题型代码量大、递归思维要求高需要整块时间反复练习。最后20天主攻二分查找、堆、位运算、数学、动态规划以及之前标记出来的难题回炉。刻意把动态规划放最后是因为它需要前面积累的数组遍历、递归、状态分析能力作铺垫。上来就刷DP容易劝退。2. 刷题顺序和知识点的重要性排序2.1 高频题型金字塔如果把这150题按面试出现概率排序我个人会排成这样优先级知识点典型特征面试中出现概率第一梯队数组、哈希表、双指针、滑动窗口代码量适中边界条件多几乎每场必考第二梯队二叉树、链表、图、回溯递归和遍历思想为主约70%的面试会涉及第三梯队动态规划、二分查找、堆有固定套路但需要大量练习约40%的面试会涉及第四梯队位运算、数学、前缀和、区间题型相对固定偶见但考到就是拉开差距的题这个排序和我刷题前的预期不太一样。我原来以为动态规划是最重要的实际刷下来发现二叉树和回溯才是区分选手的关键。原因很简单动态规划题目特征明显看到“最多”“最少”“方案数”基本能往DP上靠而二叉树题可以伪装成各种形态比如“验证二叉搜索树”“最近公共祖先”“二叉树的序列化”识别不出递归模型的人会毫无头绪。2.2 核心章节的刷题重点数组和双指针是地基。这个部分我刷得最细因为后面几乎所有题目都隐含了数组思维。比如“接雨水”这类题表面是双指针实际还可以用单调栈、动态规划做一题练三个思路。滑动窗口的题目则要重点掌握“窗口何时扩张、何时收缩”的判断逻辑这里最容易漏边界。二叉树是重头戏。递归三步法几乎能解掉大部分题目先确定递归函数的参数和返回值再确定终止条件最后写单层递归逻辑。我当时把每道树题都强制按这个模子写写多了以后看到二叉树题目第一反应不再是害怕而是先条件反射地把三个步骤列出来。动态规划的练习重点不在“状态转移方程怎么来”而在“怎么证明它是错的”。一个DP写法提交之后如果没过不是状态定义出问题就是转移漏了情况。我把每道DP题的失败提交都留档后发现最常见的错不是复杂的优化问题而是数组下标越界、初始状态没赋好这种低级错误。3. 60天里最值得反复刷的几类题目模式3.1 双指针与滑动窗口的模板化写法双指针类题目我在60天后总结出一个通用思考框架先问自己这个数组/字符串是不是有序的如果有序左右指针大概率能用。再问题目要求的是连续子串/子数组吗如果是考虑滑动窗口。最后问能不能用空间换时间用哈希表记录已经出现的数据是关键。以滑动窗口为例我的固定模板是left 0 for right in range(len(nums)): # 扩张窗口更新状态 update(right) # 当窗口不满足条件时收缩左边界 while invalid_window(): remove(left) left 1 # 记录结果 record()这套模板解决“无重复字符的最长子串”“最小覆盖子串”这类题时特别好使。关键窍门是每次只处理一个右端点的扩张左端点只在条件不满足时才动这样不会乱。双指针的核心细节更多。比如判断回文串时指针移动要跳过非字母数字字符三数之和要去重指针移动时不仅要保证left right还要跳过与上一次相同的值。这些细节我在前两次提交里全踩过到后面形成肌肉记忆了。3.2 回溯和二叉树是递归思维的试金石回溯算法的题目数量不算多但变化很丰富从排列、组合、子集到棋盘问题、单词搜索都是同一套逻辑。我把它总结成模板def backtrack(路径, 选择列表): if 满足结束条件: 记录结果 return for 选择 in 选择列表: 做选择 backtrack(路径, 新的选择列表) 撤销选择这个模板帮我拿下了所有回溯类题目。真正容易出错的是“去重”和“剪枝”。排列问题要用used数组记录哪些元素用过了组合问题去重要先排序再判断相邻元素是否相同棋盘问题要在递归前判断是否越界。我把常见的去重场景整理成了一张速查表贴在笔记里回看时非常方便。二叉树题目我没有用统一模板而是按照遍历顺序分类练习。前序遍历适合“从上到下构建”中序遍历在二叉搜索树里有天然的有序性后序遍历适合“从下往上返回信息”。一旦能够根据题目要求快速选择遍历顺序树题就成功了一半。3.3 动态规划的“五步法”练习动态规划我刷了两轮。第一轮只求能看懂题解第二轮要求自己独立推导。我用的还是业界常见的“五步法”定义dp数组的含义下标、状态推导状态转移方程初始化dp数组确定遍历顺序打印dp数组检查是否与预期一致其中最容易翻车的是第一步。很多题看似能用“一维dp[i]”解决实际状态有两个维度。比如“编辑距离”“最长公共子序列”必须用二维dp“单词拆分”虽然是一维但需要配合哈希表查词。所以每拿到一道DP题我会先把“状态”用中文完整写一遍再写代码。这个习惯帮我减少了很多无效提交。4. 实际的刷题流程、代码习惯与提效工具4.1 一道题的标准处理流程我给自己定的流程是读题后先不急着看题解自己尝试设计暴力方案哪怕复杂度很高也要写出来。在暴力解基础上思考优化点比如能否用哈希表替代两层循环、能否用双指针减少一层循环。独立思考30分钟有思路就直接动手写没思路就标记为“卡题”当天看题解但第二天必须不看题解重写一遍。提交通过后去题解区看一两个高票思路找出比自己解法更优的方案把差异记录到笔记里。每周固定抽出一天专门重刷本周记录中标记为“第二次才能写对”的题。这个过程很慢但很有效。刚开始一天只能完完整整走完一遍流程的两三题到后面熟练了一天能处理四题因为很多题目套路相同。4.2 代码习惯和复杂度意识刷题过程中代码风格同样重要。我在60天里逐渐固定了一套习惯变量名尽量用有意义的词而不是i、j、k满天飞。写left、right比写l、r更容易在思考时降低认知负担。每个函数开头先处理边界情况空数组、空字符串、只有一个元素、nums长度为1。提交前强制自己算一遍时间复杂度和空间复杂度写在注释里。面试时这一步几乎是必问题。有一类错误我反复栽跟头Python里的浅拷贝问题。列表直接赋值给结果数组后续修改原列表时会连带修改结果。比如子集、排列类题目记录结果时必须写result.append(path[:])不能直接append(path)。这种坑不看题解很难发现属于典型的环境特性坑我后面统一用深拷贝快照的方式解决了。4.3 我用到的提效工具我不太推荐过度依赖插件和可视化工具但下面几个对我的帮助确实很大本地笔记软件按知识点建页每道题记录题目链接、我的思路、复杂度、第一次错误点、最优解法的思路。刷题平台的提交记录自带统计功能我每周看一次“通过率最低的知识点”就知道接下来一周该补哪里。用Markdown维护一份“模板速查表”收录双指针、滑动窗口、回溯、二分、树的遍历等常用模板复习时只看这份表。5. 卡题、遗忘、心态崩塌60天里踩过的坑和应对方法5.1 卡题的正确打开方式卡题太正常了。150题里我独立做出来大概只有70来道其余全是看题解后理解的。卡题并不可怕可怕的是“硬扛时间”。我以前刷题有个坏毛病一道题没思路就死磕一两个小时最后又累又挫败。后来调整成“30分钟无思路就看题解”效率高了很多。看题解也有讲究。菜鸟是抄代码老手是看思路。我通常先看题解的“思路描述”部分不看代码然后关掉题解自己动手写。如果仍然写不出来再回来看代码看完后把题目标记为“需要隔天重写”。这么做能避免“眼睛会了手不会”的虚假满足感。5.2 对抗遗忘的策略60天跨度足够长遗忘是必然的。我在第20天回头看前几天刷过的数组题发现很多解法已经想不起来了当时很崩溃。后来我用了两个办法第一滚动复习。每天刷新题之前花10分钟快速浏览前一天做过的题和笔记不重写代码只看思路。刷到第50天时我已经能用10分钟过完前10天的所有题目。第二模式归类。与其记“哪道题怎么做”不如记“哪类题用什么框架”。比如看到“两个有序数组求中位数”核心是二分排除法看到“最长递增子序列”先想贪心二分能不能做再想DP。把题目抽象成模式遗忘速度会慢很多。5.3 时间不够时的取舍如果只剩两三周就要面试我会做三个取舍果断放弃“困难”级别里偏门题比如某些需要高级数据结构的题目宁可留着时间巩固二叉树和DP的基础题。“中等”难度题优先刷因为面试考察最多的就是中等题。每题只追求“能讲清思路”而非“最优解”。面试里最常见的情况是面试官并不要求你一次写出最优解而是想看你能不能从暴力优化到更优方案。这时候过程比结果重要。5.4 常见问题速查表现象原因解决办法思路正确但提交超时Python循环太慢或复杂度比预期高检查是否有重复遍历考虑用哈希表/双指针降维少数情况用sys.stdin优化IO输出结果与实际不符边界条件漏处理先补空输入、单元素输入打印dp或窗口状态递归栈溢出终止条件缺失或递归深度过大检查终止条件大型数据优先考虑迭代写法数组越界指针移动没加边界判断在访问索引前先判断上下界尤其在while循环里答案正确但内存超限创建了多余的大数组用滚动数组、原地修改、位压缩“看题解能懂自己写不出来”只是视觉记忆隔天重写把题解思路用自己的话写在笔记里5.5 独家避坑清单最后分享三个我在第40天之后才悟到的经验题目会做和能表达是两回事。刷到后半程我每周抽两三天用口述方式把解题思路讲给自己听模拟面试表达。很多刷题多的人挂在表达上代码写对却说不清为什么这在面试里非常吃亏。难度高的题对代码量的要求未必高很多时候二十行以内就能解决。如果发现自己写了六七十行还没完成大概率是思路偏了停下来重想。别在刷题数量上自我感动。day60这个节点比进度更重要的是复盘质量。我做过最亏的一件事是连续三天猛刷新题结果把前面积累的模板全忘了。定期的回溯比推进度更重要。6. 这是60天的答案不是终点费了60天刷完这150道题说句实话到了最后几天我的刷题速度已经上来了但心态反而更谨慎。因为刷得越多越知道自己不知道的还有很多。比如有些题我虽然能过但要我讲清楚证明过程还是有点虚有些DP的状态压缩写法我还在练习。这份150题更像一份“地图”刷完第一遍我总算能看清地图上的主干道了接下来要做的就是把主干道跑得更熟。如果你也正在刷这份题单或者正要开始我建议你把“刷完”当成一个起点而不是终点一边刷一边整理自己的模板库定期回头重做错题多给自己模拟面试表达的机会。一个月后你再回头看60天前的自己会明显感觉到算法思维上了一个台阶。这个感觉远比那个“day60”的打卡数字更有价值。