news 2026/10/22 22:10:05

110天刷完面试经典150:三轮刷题规划与算法面试实战经验

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
110天刷完面试经典150:三轮刷题规划与算法面试实战经验

1. 从第1天到第110天,这套经典150我是这样安排的

今天是连续刷题打卡的第110天,日期是3月11日。110天前我打开题单列表,看到“面试经典150”这套题的时候,其实没想太多,只是觉得总得找一套完整的题单作为主线,不然每天打开题库都像无头苍蝇。现在回头看,这110天里最大的收获不是“做完了多少题”,而是我终于搞清楚了:同样是刷题,有规划地刷和凭感觉地刷,效果可以差出好几倍。

这篇文章想写给正在准备技术面试的人,尤其是那种已经刷了二三十题,觉得知识点很散、不知道下一步该干什么的人。如果你还没开始,也可以照着这个节奏走。我不会讲太多抽象的道理,更多是很具体的安排、时间划分、做题顺序,以及在110天里踩出来的真实教训。

1.1 为什么是150题,而不是去“卷”几千题

现在很多刷题群的风气是比数量,谁刷了800题、1000题,就默认谁水平高。我不太认同这个思路。题量当然有意义,但“面试经典150”这套题单的设计逻辑本来就不是让你堆量,而是把面试里最高频的考点按照专题收拢起来,让你在有限时间里把每个专题的核心题型都过一遍。

它的覆盖面大致包括:数组、字符串、哈希表、双指针、滑动窗口、矩阵、链表、栈、队列、二叉树、图的遍历、回溯、分治、动态规划、贪心、位运算、堆、字典树等等。看起来很多,但拆到每个专题,真正需要反复练的核心题可能就几道。150题不是让你全背下来,而是让你通过这些题建立“题型识别能力”:看到一道新题,先能判断它属于哪个专题、大致用什么套路,再往下细化。

我的亲身感受是,刷到第二轮后期,哪怕遇到没做过的新题,也能很快找到一个可用的思考方向。这个能力不是靠题量堆出来的,而是靠把有限题目打透、反复归类形成的。

1.2 110天的时间账:60天、35天、15天,三轮各有各的任务

我见过很多人的刷题状态是“假期猛刷,开学/上班直接断档”。这种节奏最吃亏,因为算法的记忆曲线特别陡,一周不碰就能忘掉大半。我这次特意把110天切成了三段,每段目标完全不同,避免中间产生倦怠感。

第一轮是前60天,按专题刷,每天3到4题,简单题和中等题混着来。这轮不追求速度,重点是把每个专题的“常规做法”过一遍。比如链表专题就连续几天只练反转、合并、找环、删除节点;二叉树专题就集中练前中后序、层序、最近公共祖先、路径总和这类。不会写的题直接看题解,看完之后第二天必须独立重写一遍,写不出来的继续看,直到能默写为止。

第二轮是第61天到第95天,每天2题,但不再按专题,而是混合乱序。这轮的作用是打破“刚刚做完同类题所以条件反射”的假象。很多题第一轮会做,是因为你知道今天在做链表题,思路自然会往链表那边靠;但真实面试里没人告诉你考点,混合乱序能逼着你主动去判断题型。第二轮的题如果第一轮做过,就要求自己不看答案直接写,卡住超过15分钟才允许回看错题本。

第三轮是第96天到第110天,也就是最后这半个月,进入限时模拟状态。每天1到2题,中等题限时25分钟,困难题限时40分钟,到点不管做没做完都停笔,然后对照题解找差距。这一轮练的是“面试状态”而不是“学习状态”:你需要在有限时间内完成审题、思路、编码、自查四件事,缺一个环节都要在回看时重点标记。

1.3 三轮之间的衔接,比每一轮本身更重要

每轮结束时我都会做一次总结,把这一轮里反复卡壳的题目单独摘出来,形成一份“待爆破清单”。第一轮结束时的清单最长,差不多有40多道;第二轮结束时就只剩十几道;到第三轮开始前,我特意先把这些薄弱题重新做了一遍,再去进入模拟训练。

这个衔接动作很关键。很多人刷完一轮就开始下一轮,中间不做任何筛选,结果第二轮还在重复犯第一轮的错误。我的经验是,每次切换阶段之前,至少留出2到3天,只做旧题不做新题,尤其是把那些“看着眼熟但写不全”的题重新手写一遍。这个过程很痛苦,但能把欠下的债还掉大半,后面再滚动复习时才会越来越轻松。

2. 3月11日当天的复盘:一道滑动窗口题从草稿到提交的完整经过

到了第三轮,我每天的安排非常固定:早上挑一道中等题,限制25分钟,用计时器倒计时,全程当成真实面试来对待。3月11日这天抽到的还是一道滑动窗口题,题目大意是给出一个字符串,要求找出其中不含重复字符的最长子串的长度。这类题在经典150的“滑动窗口”专题里算是标准题,但我当天想留作复盘样本,因为这道题特别能看出一个人的基本功。

2.1 拿到题目后的前3分钟:先想暴力解,再想优化方向

很多新手拿到算法题就急着动手写最优解,结果往往卡在中间写不下去。我的习惯刚好相反,先快速在脑子里过一遍暴力做法,把最朴素的解法想清楚,再开始优化。

这道题的暴力解法很直观:枚举所有子串,逐个检查有没有重复字符,记录最大长度。假设字符串长度是n,枚举起点和终点是O(n^2),检查重复字符如果用哈希集合就是O(1),整体复杂度O(n^2)。当n是10^5级别的时候,这个复杂度显然过不了,但想清楚暴力解能帮你确认两件事:一是结果的计算方式(最大长度),二是数据规模是否真的需要优化。

接下来考虑优化的方向。暴力解慢在重复检查了大量子串,我们真正需要维护的其实是“当前没有重复字符的连续区间”。这个直觉一出来,滑动窗口就顺理成章了:右指针不断向前扩展窗口,左指针只在窗口内出现重复字符时向右移动,直到把重复字符移出去为止。

2.2 从O(n^2)到O(n):当时我是怎么一步步逼近最优解的

我实际写出来的核心逻辑是这样的:

left, ans = 0, 0 window = set() for right, ch in enumerate(s): while ch in window: window.remove(s[left]) left += 1 window.add(ch) ans = max(ans, right - left + 1)

这段代码看起来简单,但里面藏着几个容易出错的地方。首先是while循环而不是if:当右指针遇到的字符已经在窗口里时,左指针可能要连续移动多次,才能把所有重复字符清出去。我第一遍写的时候就因为用了if条件,导致窗口里仍然残留重复字符,答案比预期大。

其次是窗口移除的时机。先移除s[left]再移动left,顺序不能反。如果先left += 1再remove,就会移除错字符。这类问题代码只有几行,但错误藏得很深,提交后很难通过肉眼发现。

最后是答案更新时机。right指针每次扩展后,当前窗口都是“无重复”的合法窗口,所以必须每次都取一次最大值,而不是只取最终状态。我见过有人把ans = max(...)写在循环外面,那样只能得到最后一个窗口的长度,会漏掉前面更大的窗口。

2.3 提交之后,我还会补上三件事

代码通过只是第一步。当天我提交通过后,又做了三件事:第一,在题解区找一找是否有更巧妙的解法。这道题的通用进阶做法是用哈希表记录每个字符最新出现的位置,这样左指针可以直接跳跃到重复字符的下一位,不需要像set版本那样一步步挪。虽然最坏复杂度同样是O(n),但常数更小,而且思路值得借鉴。

第二,把这道题记为“滑动窗口-字符去重”类型,并在错题本里写清楚我的易错点是while条件写成了if。第三,把模板代码重新整理到自己的模板笔记里。所谓模板不是背代码,而是记结构:维护窗口、条件收缩、更新答案,这三步分别对应代码里的哪几行。有了这个结构,后面遇到“最长连续无重复”“最少替换次数”“最长覆盖子串”这类变体,都能迅速套用。

3. 按专题拆150题:每个专题真正需要掌握的“内核”

经典150的题单是按专题组织起来的,我的建议也是按专题过。但专题和专题的侧重点差别很大,下面把我实际刷下来之后的总结写出来,按数据结构大致分一下类,并给出每个专题最容易忽略的地方。

3.1 数组、哈希表与双指针:高性价比的第一站

数组类题目几乎是所有刷题人的起点,也是面试里出现频率最高的一类。经典150里这部分题很多,重点集中在几个方向上:两数之和/三数之和类问题、盛最多水的容器、合并区间、轮转数组、除自身以外数组的乘积等。做这部分时,我体会最深的是“哈希表空间换时间”和“排序+双指针”这两个套路。

两数之和这类题,常见的进阶方向是三数之和、四数之和。核心思路都一样:先排序,再固定一个数,剩下两个数用双指针从两端向中间逼近。这里最需要小心的是去重:指针移动时如果遇到相邻相同元素,要跳过,否则会出现重复三元组。我第一轮刷三数之和时,连续三次提交失败,原因都是忘了在找到一对结果后同时移动左右指针并跳过重复值。

合并区间也是一个容易出细节问题的题。排序之后,判断两个区间是否重叠,条件是当前区间的左端点是否小于等于上一个区间的右端点。如果写成小于号,正好相邻的区间就会被错误拆开。这类边界条件不跑几个用例很难发现,只能靠熟能生巧。

3.2 链表、栈与队列:指针操作必须形成肌肉记忆

链表题在面试里的地位很高,因为它考的不是复杂算法,而是对引用的理解。反转链表、合并两个有序链表、环形链表、删除链表的倒数第N个节点、回文链表,这些题都属于“会者不难,难者不会”的类型。如果连续两周没碰链表,再写反转链表大概率会卡住,所以我建议链表题二刷间隔要短。

链表题最大的技巧是引入哑节点(dummy head),它能统一处理头节点被删除或更换的情况。另一个重要经验是“先画图再动笔”,尤其是指针重连顺序。例如反转链表的经典三指针写法,必须先保存后继节点,再断开当前节点的next,否则整条链表就丢了。很多人在白纸上能写对,一上机就写错,根本原因还是没有形成条件反射。

栈和队列方面,经典150里出镜率最高的是有效括号、最小栈、字符串解码、每日温度。这类题考的是对“单调栈”的理解:什么时候用栈、什么时候弹栈、栈里应该存下标还是值。以每日温度为例,核心思路是从右往左遍历,维护一个温度递减的栈,弹出所有小于当前温度的索引,栈顶就是答案。这里很多同学卡壳的原因是不知道该存温度还是存下标,事实上答案需要天数,所以栈里必须存下标,温度通过下标回数组取。

3.3 二叉树与图:把DFS/BFS模板改造成万能工具

二叉树是另一个面试大热门,经典150里涉及二叉树的部分非常多:前序、中序、后序、层序遍历,最大深度、最近公共祖先、路径总和、二叉搜索树相关题目。二叉树题的秘诀在于“递归序”:把递归函数想象成访问每个节点的固定流程,先处理当前节点、再处理左子树、再处理右子树,分别对应前序、中序、后序。能把递归序想明白,绝大部分二叉树题都能拆成“递归三部曲”:确定入参和返回值、确定终止条件、确定单层递归逻辑。

图的问题复杂一些,经典150里最常考的包括岛屿数量、腐烂的橘子、课程表、单词接龙等。岛屿数量是标准的DFS/BFS染色问题,核心思想是遇到陆地就向四个方向扩展并标记以免重复访问。腐烂的橘子是典型的多源BFS,需要把初始腐烂的橘子作为多个起点同时入队。这类题很容易踩的坑是递归爆栈或队列死循环,解决办法是入队的同时立刻标记已访问,而不是出队时才标记。

3.4 回溯、动态规划与贪心:三兄弟的思考顺序要分清

回溯、动态规划和贪心这三类算法,大概是新手最痛苦的部分,因为它们的解题思路都是“多阶段决策”,但适用场景完全不同。我的经验是拿到题先问自己几个问题:需要输出所有解吗?需要的是最大最小值吗?每一步做局部最优选择能保证全局最优吗?

回溯适合“枚举所有可行解”的问题,典型如组合、排列、子集、分割回文串。它的框架非常固定:递归函数里先处理结束条件,再枚举当前可选择项,做选择、递归、撤销选择。最容易忘的是“撤销选择”,导致结果里混入之前路径的残留。

动态规划适合“求方案数、最大最小值”且问题有最优子结构的情况。做动态规划的核心不是背状态转移方程,而是先把dp数组的下标含义写清楚,再推导递推关系。比如经典的爬楼梯问题,dp[i]表示到第i级的方法总数,递推关系就是dp[i]=dp[i-1]+dp[i-2]。如果下标含义没想清楚,后面全是空中楼阁。

贪心的难点在于证明。跳跃游戏、买卖股票、分发饼干这类题,代码往往很短,难的是判断“贪心到底对不对”。我的建议是,先尝试构造反例,如果构造不出来,再用递推验证。实际面试时不需要严格数学证明,但至少要给一个“为什么局部最优能凑成全局最优”的直觉解释。

3.5 专题总结表:经典150核心专题的快速索引

整理一个极简的索引表,是我每轮复习都会拿出来过一遍的东西,也方便你对照检查自己的知识盲区:

专题高频考察点核心思路最容易踩的坑
数组/哈希/双指针两数之和、三数之和、合并区间、盛水容器排序+双指针,哈希表换时间区间重叠判断、去重条件
链表反转、合并、找环、删倒数节点哑节点、三指针、快慢指针指针重连顺序、丢节点
栈队列有效括号、单调栈栈存下标、按需求弹出存值还是存下标
二叉树遍历、最大深度、公共祖先递归序、DFS/BFS模板终止条件、返回值的定义
回溯全排列、组合、子集选择+递归+撤销忘记撤销、重复结果不过滤
动态规划爬楼梯、打家劫舍、零钱兑换明确dp含义再写递推dp下标含义混乱、边界状态错
贪心跳跃游戏、买卖股票局部最优推全局最优贪心需要证明,别上来就写

这张表不是让你背,而是用来刷完一部分题后自查。如果某个专题让你说不出核心思路,说明还需要回炉。

4. 110天里最值钱的不是题解,是这几类错误记录

刷到后期我发现一个现象:让我进步最快的,不是那些一遍就过的题,而是反复出错的题。每次提交失败背后基本都是三类问题:复杂度估算错误、边界条件漏判、审题不仔细。下面把每一类展开讲,并给出我的排查方式。

4.1 复杂度估算错误:以为能过的代码卡在超时上

我碰到过的最典型场景是:代码写得顺,样例全过,一提交就超时。原因往往是在设计阶段没有估算数据规模。比如题目数组长度是10^5,两层循环就是10^10次操作,任何语言都会超时。这个坑在第一轮刷简单题时不明显,因为简单题的数据规模往往比较小,到了中等题数据规模一上来就露馅。

我的排查方法是提交前先看数据范围,第一步写下一个大概的复杂度目标:如果n是10^5,那么单循环O(n)或带log的O(n log n)是安全区;如果是10^3,O(n^2)也勉强能接受;但如果n到10^5还想用O(n^2),基本可以提前宣告失败。这个判断练多了之后,再也不会出现“写完才发现复杂度不对”的情况。

4.2 边界条件漏判:空输入、单元素、最大值与最小值

边界条件大概是面试里最容易被扣分的点。很多人面试时算法讲得头头是道,代码写完也没有语法错误,但面试官随口问一句“如果输入为空呢”,马上就答不上来。这暴露的是做题习惯问题,不是知识储备问题。

我的个人习惯是写代码时顺手处理三组测试用例:空输入、只有一个元素、全是重复元素。如果题目涉及数值运算,再补一组极大值和极小值的用例。以滑动窗口那道题为例,空字符串要返回0,单字符要返回1,全重复字符要返回1。这三个用例看似简单,却能覆盖大多数错误。链表题里处理空链表和只有一个节点的链表,也是同一个原则。

4.3 审题问题:把“至少”“连续”“最多”看漏

这是我个人犯过的很蠢但也很典型的错误。有些题目会在关键词上埋坑:要求“至多k次”和“恰好k次”是两种完全不同的解法;“连续子数组”和“子序列”是两种难度;“非递减”和“递增”差了一个等号。我曾在做数组题时,把“最多包含两个不同元素”看成“最多包含两个重复元素”,结果思路完全跑偏,浪费了半小时。

后来我总结了一个笨办法:读题时把题目里的限制条件用笔划出来,尤其是“连续”“非空”“至少”“最多”“原地”“相对顺序”这种词。刷题软件上看题可能没那么方便,但可以在草稿纸上把要求重写一遍。宁可花30秒审题,也不要写十分钟后发现方向错了。

4.4 错题本的整理方式:重点写“下次如何避免”

很多人的错题本是抄代码,抄得工工整整,之后再也没打开过。我的错题本只有三栏:错误类型、具体表现、下次如何避免。以边界条件漏判为例,我会写:错误类型是“边界漏判”,具体表现是“数组长度为1时返回了0”,下次如何避免是“写完后默念三遍:空、单、双、全、极”。这样回看时才真正有用。

每次给题目分类时,我会顺手统计当前最容易犯的错误类型。110天下来,我的超时问题从最开始占四成降到不到一成,边界问题也是一路下降。这个过程很奇妙,不是说后面遇到的题变简单了,而是因为我知道自己最容易在哪里栽跟头,写完就会主动自查,错误率自然就下来了。

5. 从“刷完150”到“面试能开口”:最后这段转化训练最重要

如果你以为刷完题就能直接面试,那还差一步。我的真实体会是:刷题是“输入”,讲题是“输出”,这两者之间有一道明显的分界线。很多人能闷头把代码写对,但被问一句“你讲讲这题思路”就支支吾吾。第三轮我专门练了这件事,效果很好。

5.1 能AC不等于会说,讲题也有固定顺序

面试里讲题,不是从代码第一行开始念,而是要让面试官快速理解你的思路。我练出来的顺序是四步:第一步复述题意,用自己的话说清输入输出;第二步说暴力解,为后面的优化做铺垫;第三步说优化思路,点出关键观察点,比如“这里我们只需要维护窗口,因此用双指针”;第四步说复杂度和边界情况。

这四步里,第二步最容易被人忽略。有的同学喜欢直接讲最优解,觉得暴力解说出来丢人。实际上,先讲一句“暴力做法是枚举所有情况,复杂度是O(n^2)”,反而能让面试官觉得你有对比意识,知道为什么需要优化。我自己在线下模拟时试过两种讲法,明显是“先暴力再优化”更容易让听的人跟上节奏。

5.2 复杂度分析别再背术语,试着用口语表达

面试时很多人脱口而出“时间O(n),空间O(n)”,然后就没了。其实面试官更希望听到你能解释清楚:为什么是O(n)?我说得最多的一句是“每个元素最多被访问常数次,所以总操作次数随着n线性增长”。听起来比干巴巴的O(n)更有说服力。

空间复杂度也是同理。递归类题目一定要说清楚递归深度最坏到多少,以及每层递归消耗多少额外空间。我在二叉树题目上吃过亏,递归深度在最坏情况下就是链表形态,等于n,空间复杂度不是O(logn)而是O(n)。这类细节最能体现基本功。

5.3 线上模拟面试怎么安排、怎么复盘

第三轮我每周做三次线上模拟面试,每次控制在45分钟,只做两道题。整个流程完全模仿真实场景:先读题,把自己想说的思路原原本本讲出来,再写代码,最后自己跑测试用例。结束后马上回看录像,记录三个问题:哪一步想的时间最长、哪一句话没说清楚、代码里有没有边界遗漏。

回看这一步特别重要。有一次我发现自己在一道题上纠结了8分钟没有动手,原因是没想清楚数据结构。这种问题不看录像根本不会意识到。及时复盘才能在下一次刻意调整。

5.4 面试前一周,把错题本变成唯一的复习资料

到了面试前一周,我的原则是绝对不再做新题。新题容易制造焦虑,而且边际收益很低。这时候我只看三样东西:模板笔记、专题索引表、错题本。模板笔记帮助快速恢复肌肉记忆;专题索引表帮我从题目反推考点;错题本则提醒我所有容易犯的错误。

最后再分享一个对我帮助很大的小技巧:把题目按“第一遍会做/第二遍会做/目前还卡”分三档。面试前只需要重点回看第三档,其他两档扫一眼就行。这种分档方式比按题目顺序重新刷一遍节省大量时间,而且能保证宝贵的复习时间全部花在刀刃上。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 22:09:01

基于机器学习的水果缺陷分选:Matlab图像处理与分类器实现全流程

你如果在果蔬加工、产后处理或者农产品检测这块待过,大概都会遇到同一个头疼事:怎么又快又稳地把带病斑、有损伤、卖相差的果子挑出去。靠人工肉眼分选,效率低不说,标准还飘忽不定,同一个果农上午挑的和下午挑的判据都…

作者头像 李华
网站建设 2026/10/22 22:02:13

Spring Boot + Spring AI 构建生产级 Java AI Agent 实战

1. 这个项目到底在解决什么问题Java 生态里做 AI Agent,一直有个尴尬的断层。Python 那边 LangChain、LlamaIndex 玩得飞起,各种 Agent 框架层出不穷,但 Java 开发者想搞一个能上生产的智能体,要么硬着头皮跨语言调用,…

作者头像 李华
网站建设 2026/10/22 21:54:17

多Agent系统可靠性治理:AgentGate框架设计与实践

这两年我前后手搓过好几种多Agent系统,从两三个Agent配合干活的轻量脚本,到十几个Agent协同的模拟生产项目,最深的感受是:单个Agent偶尔犯错不可怕,可怕的是多个Agent凑在一起之后,错误会互相放大、互相传染…

作者头像 李华
网站建设 2026/10/22 21:54:15

Kafka单节点能扛多少数据?消费负载均衡为何不按IP路由

1. 先回答那个最常见的误解:单节点到底能扛多少数据量我经常在社区里被问到同一个问题:“Kafka单节点到底能承载多少数据量?”问这个问题的人,十有八九都看过营销号里“百万TPS”之类的夸张说法,真正落到自己的集群上时…

作者头像 李华
网站建设 2026/10/22 21:54:06

Agent治理:从不可控运行到可编程调控的范式跃迁

1. 当我们说“Agent治理”时,到底在谈什么——从Codex插件出现前的混沌现场说起 很多人看到标题里“Agent治理”四个字,第一反应是:这又是个新造的概念包装吧?不就是写几个函数、调几个API、再套个LangChain模板吗?我试…

作者头像 李华
网站建设 2026/10/22 21:50:55

VT_X64硬件虚拟化进程保护:EPT与VM-Exit深入源码解析

简介:一份面向64位系统安全研究与驱动开发的VT源码包,基于Intel硬件虚拟化技术,围绕进程保护与进程隐藏两大目标,为安全工程师、驱动开发者及虚拟化技术爱好者提供可直接借鉴的实现参考。压缩包共26个文件,体积仅240KB…

作者头像 李华