春招实习这一路,我大概把能踩的坑都踩了一遍。写这篇面经的时候,我已经拿到了几个算法岗实习的offer,回头看看那段从简历石沉大海到面试被问到怀疑人生的日子,很多东西确实值得记录下来。标题就很直白,弱校本科生,算法岗,春招实习。这三个词放在一起,本身就带着一种不太容易的味道,但这篇文章想说的恰恰是,这条路虽然难,但不是走不通。以下内容全部基于我个人在春招期间的真实面试经历,按面试环节和时间线整理,每道题都尽量还原当时面试官问的方式,再附上我的复盘和后来补课得到的理解,希望对背景类似的朋友有点帮助。
1. 写在前面:弱校本科生到底难在哪,以及我是怎么准备的
先交代一下背景。我本科学校是双非,专业是计算机科学与技术,没有名校光环,没有顶会论文,实验室资源也一般。投算法岗春招实习之前,我一度很犹豫,因为身边几乎没有人走这条路,大家默认算法岗是985硕士的天下。但仔细想了一下,算法岗也分很多种,有做纯研究发paper的,也有做业务落地调模型的,后者对工程能力和动手能力的要求其实很高,本科学历虽然吃亏,但并不是完全没有机会。春招开始前大概三个月,我花了大量时间做两件事:刷题和整理项目。
刷题我主要用的是LeetCode和AcWing,按照高频考点去刷,一开始没有盲目追求题量,而是先保证每个类型的题目都能独立写出最优解。我之前听说过很多人说刷了三百题四百题,但我觉得刷题这东西,数量只是一方面,一遍两遍地重复更重要。我的策略是,先把数组、链表、二叉树、堆、栈这些基础数据结构吃透,然后上排序、二分、双指针、滑动窗口、DFS、BFS,最后再啃动态规划和图论。时间不够的情况下,优先保证核心题型足够熟练,冷门题型至少知道思路。
项目这块,我没有实习经历,主要靠的是自己做的两个项目,一个是基于公开数据集的推荐系统,另一个是一个自然语言处理相关的文本分类方案。这两个项目都不算惊艳,但好在我把每个细节都摸了一遍:数据怎么清洗、特征怎么构造、模型怎么选、评估指标怎么定、踩了什么坑、后来怎么改的。面试官问项目的时候,最怕的就是一问三不知,所以我把每个项目的每一个环节都写成文档,反复过了好几遍。
还有一个很重要的准备,就是面试复盘。我每面完一场,都会把面试官问的问题记下来,包括那些我当场没答出来的,然后回去翻书、查博客、补知识。这些复盘内容就成了我后面面试的弹药库。说句实在话,面经这东西,看别人的只是图个心理安慰,真正有价值的是你自己在面试现场被问到然后事后搞懂的那些题。
2. 算法题面经汇总:那些被问到手撕的代码题
算法题是算法岗面试里最硬核的一关,每个公司都在考,而且考得很直接,就是让你写代码。我面的公司里,有让你在在线编辑器里直接写的,也有让共享屏幕在本地IDE里写的,还有连写都不写,直接口述思路的。下面这些是我遇到的题目里比较典型的一些,按考点分类整理。
2.1 高频基础题:排序、二分、链表与数组操作
排序算法几乎是必考。我印象比较深的一次是面试官让我写快速排序,写完之后追加了一个问题:快排在什么情况下会退化成O(n²),怎么优化。这就是典型的一题两问,代码写完还得说原理,当时我除了回答“基准值选得不好会退化”之外,还补充了随机选基准和三数取中的方案,面试官看起来比较满意。
还有一道让我手写冒泡排序的题目,我当时有点意外,因为太基础了。但面试官的后手问题是:这个排序稳定吗,为什么,它和插入排序相比谁更优。所以不要以为考得简单就是放水,恰恰是在这些简单题上能拉开差距。回答的时候一定要把“为什么”讲清楚,而不是背出代码了事。
二分查找也考过几次,考法比较灵活。一次是让我在一个有序数组中找目标值的第一个和最后一个位置,这就是LeetCode 34。另一次是让我实现一个求平方根的函数,要求精确到小数后若干位,这个是二分答案的经典应用,我用了浮点数二分的写法,然后用左右边界逼近。注意浮点数二分不能直接比较等于,要用精度范围去判断,这个细节面试官可能会有追问。
链表相关的题目里,我遇到的是反转链表和判断链表是否有环。反转链表我写了迭代版,面试官又问能不能用递归写,这个基本功得会,两种写法都要熟练。判断链表是否有环我用的是快慢指针,写完后面试官追加了一个问题:如果链表很长,快慢指针会不会有性能问题。这个就涉及到时间和空间复杂度分析了,答案是O(n)时间和O(1)空间,性能没有问题。
数组操作类的题目,我遇到过合并两个有序数组、移动零、最大子数组和。这几道都属于“看起来简单但写起来要稳”的题,考察的是边界条件处理能力。比如合并两个有序数组,我记得题目要求从后往前填充,这样可以避免覆盖原数组元素,这个思路如果之前没见过,现场想可能要卡一会。
2.2 字符串专题:KMP、回文与模拟题
字符串是算法岗面试的座上宾,尤其是KMP算法,几乎每一轮技术面都有可能被问到。我面试的时候确实被要求手写KMP的next数组。当时面试官给的模式串是类似"abacaba"这样的形式,要求写出next数组的求解过程。这里有个小坑,不同教材里next数组的定义不完全一样,有的从0开始,有的从-1开始,有的next[i]表示最长公共前后缀长度,有的表示失配后跳转的位置。我当时先和面试官确认了一下定义,然后按照next[i]表示“失配后模式串回退到的位置”这个口径来写,这样写出来就是-1、0、0、1、0、1、2这样的序列(从0下标开始,next[0] = -1)。
KMP的优化也值得注意。传统next数组在模式串出现连续重复字符时会造成多余比较,这时可以用nextval优化。我在一次面试中提到了这个点,面试官明显来了兴趣,追问了具体怎么优化,以及什么时候该用nextval。我的回答是,若p[i] == p[next[i]],那么失配后跳转的位置还要继续往前跳,所以把next[i]更新为next[next[i]],这样避免了重复匹配同一个字符。
字符串里我还遇到过一个回文串判断的题目,要求判断一个字符串能否通过删除最多一个字符变成回文串。经典的贪心思路,左右指针,遇到不相等时尝试删左边或删右边,递归判断即可。另外还有一道模拟类的字符串题,要求实现一个简单的规则解析器,类似把"a2[b3[c]]"展开成"abcccbccc"这种形式。这类题看着陌生,其实就是用栈模拟展开过程,当时我把数字和字符分开压栈,遇到']'就弹栈展开,有点绕但能写通。
2.3 数据结构与二叉树:遍历、路径与最近公共祖先
二叉树算是算法岗面试里出现频率比较高的数据结构了。前序、中序、后序遍历当然要能手写,而且还可能问非递归版本。我遇到一次面试官让我同时用递归和栈模拟两种方法写中序遍历,然后分析两者思路上的差异。递归版本的顺序是“左-根-右”,非递归版本需要用栈来模拟系统栈的行为,先把左子树一路压栈,弹栈访问根节点后再转向右子树,这个思考过程其实比背代码重要得多。
二叉树层级遍历也是高频题,我用队列实现,每一轮记录当前层的节点数,然后一次性处理完整个队列,这样就能按层输出。面试官追加的问题是:如果要求从下往上、从右到左输出每一层怎么办。这个本质就是把结果反转,或者调整遍历顺序,思路不难,关键是能不能快速反应过来。
二叉树的最近公共祖先(LCA)我遇到过一次,题目比较经典,递归判断左右子树是否包含目标节点。如果是二叉搜索树的LCA,就可以利用左小右大的性质直接迭代判断。我那次遇到的是普通二叉树,所以写了递归。面试官追问了时空复杂度,以及如果这棵树会频繁查询LCA,应该怎么预处理。我当时想到了用倍增法维护节点的祖先信息,但说了个大概,现场没完全说好,事后补课才真正弄明白倍增法的细节,这个是典型的“听过但没吃透”的教训。
路径类题目我还遇到过一个,求二叉树中所有根到叶子路径上节点值之和为某个目标值的路径。就是DFS加回溯,维护当前路径节点列表,到叶子节点时判断路径和是否等于目标值。这个题比较常规,但考察的是代码的严谨性,比如什么时候把结果加入答案、什么时候回溯。
2.4 图论与搜索:DFS、BFS、拓扑排序与最短路
图论的题目在实习面试里出现的频率不如前面那些高,但一旦出现就挺考验人。我遇到过一个求岛屿数量的题目,就是二维网格里1表示陆地,0表示水,问有几个连通的陆地板块。这题本质是连通块计数,用DFS或者BFS都能做,关键是访问标记的处理,别重复遍历,也别漏遍历。我当时写的是DFS,每发现一个陆地就把它所属的整个连通块标记为已访问,然后计数加一。面试官追问了空间复杂度,如果网格特别大,递归会不会栈溢出,这个就得注意,DFS的递归深度跟连通块大小有关,极端情况下可能爆栈,这时候可以改成显式栈或者BFS。
拓扑排序也考过一次,场景是课程表先修关系判断能不能修完所有课程。这就是判断有向图是否存在环的问题,用Kahn算法维护入度为0的节点队列,每弹出队列就对邻接节点的入度减1,如果最后处理的节点数不等于总节点数,就说明有环。这个算法思路不算难,但写起来要细心,邻接表要建对,入度数组要更新对。
最短路径我遇到的是Dijkstra算法。面试官没有直接让我写完整代码,而是让我讲思路,然后针对某个细节追问:如果边权有负数,Dijkstra还能用吗,为什么,应该改用哪个算法。这就是在考底层原理,答案是Dijkstra基于贪心每轮确定一个最短距离的节点,有负权边的时候贪心失效,需要用Bellman-Ford或SPFA。这题我答上来了,因为我之前专门把最短路径类算法的原理对比过一遍。
二分图相关的算法虽然面试时没有被直接要求手写,但我自己准备过匈牙利算法和HK算法,后来在一次面试的闲聊环节被问到“你了解哪些匹配算法”的时候派上了用场。算法岗面试除了写题,也会考察知识广度,知道一些经典算法的名字和适用场景,偶尔会有意外收获。
2.5 动态规划:背包、区间DP与状态设计
动态规划是我面试里遇到的最多的类型之一,也是我花时间最多的部分。最长递增子序列考过,我用的是O(n²)的DP思路,面试官追问能不能优化到O(n log n),这就涉及到耐心排序的贪心加二分的做法,维护一个tails数组,每个元素表示当前长度的递增子序列的最小末尾值,然后用二分找到插入位置。
背包问题我遇到过一次,是一个“子集和能否达到目标值”的变体,本质是0-1背包,用一维滚动数组优化空间。当时面试官问了一个从没遇到过的问题:如果每个物品可以用无限次,状态转移方程应该怎么改。这就是从0-1背包变完全背包,遍历顺序从倒序变成正序,我当时解释了一下为什么顺序变化会导致同一个物品被多次取用,面试官点头了。
还有一个区间DP的题目让我印象深刻,是经典的“戳气球”问题。这个题我当时没写出来,只想到了递归的思路,但状态定义一开始想错了。面试结束后我花了一天时间专门把区间DP的题目刷了一遍,才算真正理解了为什么这类题要先枚举区间长度,再枚举左端点,再枚举分割点。这个经历让我明白了,面试题答不上来不代表这件事就结束了,把它学会,后面的面试才有意义。
2.6 贪心、排序检索与搜索策略题
贪心算法的题目,我遇到过一个会议室安排问题,就是给定若干时间段,问最多能安排多少个不重叠的会议。经典解法是按结束时间排序,然后贪心地选择结束时间最早且不与之前冲突的会议。这题的证明思路是“替换法”,贪心选择的方案可以通过交换操作替换成某个最优解而不改变结果,理解了这个证明思路,同类题目都能串起来。
搜索策略里,面试官问过“有哪些常见的剪枝策略”。我结合自己刷搜索题的经验,回答了几类:可行性剪枝、最优性剪枝、重复状态排除、启发式排序,以及位运算状态压缩。面试官接着问我有没有用过模拟退火算法或者粒子群算法。这个就有点超纲了,我只是了解过原理,没有实践过。我如实说了,然后简单讲了一下模拟退火的核心思想,就是在搜索过程中以一定概率接受劣解来跳出局部最优,温度逐渐下降,接受概率逐渐减小。面试官也没有为难我,说明诚实交代自己不会,并且能把知道的一部分讲出来,比硬编一个答案要好。
2.7 手撕代码的小技巧与注意事项
手撕代码环节,除了题目本身,有几个细节非常影响面试观感。首先,写代码之前先和面试官确认一下输入输出格式和边界条件,比如数组长度、值的范围、是否为空,这些确认过程能让面试官看到你的工程意识。其次,动手写代码的时候,变量命名尽量有意义,不要全是i、j、k,偶尔用用left、right、index这类的单词,代码会干净很多。第三,写完之后主动说一遍时间复杂度和空间复杂度,如果还有优化空间,自己提出来比面试官提醒要好得多。最后,写完代码不要急着说“写完了”,先自己顺着代码逻辑跑一个简单例子,能当场发现大部分低级错误。
3. 机器学习与深度学习理论面经:八股文的正确打开方式
算法岗面试里的理论问题,和学校里考名词解释完全不一样。面试官会更喜欢用“场景+追问”的方式考察你对原理的理解深度。我整理了我在面试中被问到的一些代表性的问题,按主题分类写在这里。
3.1 经典机器学习:回归、树模型与SVM
让我比较意外的是,实习面试里传统机器学习的内容反复出现,尤其是决策树和集成学习。面试官问过:XGBoost和GBDT的区别是什么,XGBoost做了哪些优化。我当时的回答是:XGBoost在GBDT的基础上做了二阶泰勒展开,用了正则化项来控制模型复杂度,支持列采样,并且在特征分裂点的寻找上做了并行化处理。面试官接着问,为什么二阶信息比一阶信息更好。我的理解是,二阶梯度蕴含了一阶梯度变化趋势的信息,对目标函数的近似更精确,因此每一步的提升方向更准。
SVM也被问到过几次。经典问题是:SVM的损失函数是什么,为什么要用合页损失,以及软间隔中的C参数有什么作用。合页损失在置信度大于1且分类正确时损失为0,而小于1时会有线性惩罚,这样既保证了分类正确,又保证了足够大的分类边界。C参数控制着对误分类样本的惩罚力度,C越大,模型越不愿意容忍错误,可能过拟合;C越小,模型泛化能力可能更好但也可能欠拟合。这些回答如果离开公式直接讲直觉,会让面试官觉得你只背了结论,最好还是在脑子里形成那个几何图像再回答。
逻辑回归是我被问到最多的问题之一。面试官问过:逻辑回归的损失函数为什么用交叉熵而不是均方误差。这个问题要从优化角度回答,交叉熵损失关于参数的梯度里含有预测误差项,而均方误差的梯度里还含有sigmoid导数的因子,当预测值接近0或1的时候,梯度会变得非常小,导致收敛速度极慢。
聚类算法里,K-Means被问过:初始点怎么选,K值怎么确定。我当时提到了K-Means++和肘部法则。面试官还追问了K-Means对异常值敏感为什么,我当时回答是因为平方误差里异常点会产生大距离误差,从而拉偏簇中心。这块后来我也复习了DBSCAN这类基于密度的算法,因为面试官后面问了一句“如果数据分布不是球形怎么办”,从K-Means切换到DBSCAN来回答就很自然。
3.2 深度学习基础:CNN、激活函数、梯度消失与网络结构
深度学习的内容也是重头戏。CNN的问题从基础到进阶都有,常见的有:卷积的感受野怎么计算、参数共享有什么用、为什么堆叠小卷积核能替代大卷积核。最后一问我当时有点卡壳,后来想明白了,两个3x3卷积堆叠的有效感受野是5x5,参数数量却比单个5x5卷积少,并且中间多了一层非线性变换,表达能力更强,这也是VGGNet设计的核心思想之一。
激活函数的问题也几乎每场必考。面试官会问:ReLU和sigmoid相比有什么优势,ReLU有哪些缺点,怎么缓解。ReLU的优势是计算简单、正区间梯度恒为1、能减缓梯度消失,但缺点是负区间输出恒为0,可能导致某些神经元永远不激活,也就是Dead ReLU问题,缓解方案包括使用Leaky ReLU、PReLU或者像ELU这样的替代版本。
梯度消失和梯度爆炸的原理我也被问到过。回答这类问题,要先从反向传播的链式法则出发,说明梯度是连续相乘的结果,如果每层乘子都小于1,多层相乘后梯度会指数级变小,如果都大于1则会指数级增长。缓解手段包括合理的权重初始化、使用Batch Normalization、调整激活函数、使用残差连接以及梯度裁剪。残差连接在如今的大模型里也无处不在,它让梯度可以走一条“高速公路”直接传回浅层,解决了深层网络难以训练的问题。
在大模型知识点上,我被问过Self-Attention的原理和Transformer的结构。自我感觉这块准备得相对充分,我把Q、K、V三个矩阵的来源,缩放点积注意力的公式,以及为什么除以根号d_k避免点积结果过大进入softmax饱和区都讲了一遍。面试官追问了位置编码的作用和为什么Transformer需要位置编码,这是因为Attention本身不包含顺序信息,词序变化后输出会完全一样,所以必须靠位置编码把位置信息注入输入序列。在面向大模型应用的团队里,还会追问一些和推理、部署相关的问题,这块我实践不多,主要靠看资料了解过一些。
3.3 模型评估、过拟合与样本不平衡问题
模型评估这一块,我被问过精确率、召回率、F1、AUC的含义和适用场景。尤其在正负样本极不平衡的情况下,准确率会严重失真,这时候更适合用AUC或者PR曲线来评估。面试官追问:AUC为什么对样本不平衡不敏感。AUC只依赖排序结果,不依赖预测值绝对值,所以正负样本比例改变时,如果模型对样本的排序基本不变,AUC的变化就不会太大,这和准确率判定的方式是完全不同的。
过拟合的识别和解决也是标准问题。我通常会分几个层次回答:数据层面可以扩充数据、做数据增强;模型层面可以降低模型复杂度、加正则化、做Dropout;训练层面可以用早停法、交叉验证、简化特征集。面试官如果追问为什么Dropout能防止过拟合,可以从集成学习的角度回答,每个batch训练的是不同的子网络,最终是无数子网络的集成效果,所以泛化能力强。
样本不平衡问题,面试官问过:如果正样本只占1%,你怎么训练分类模型。我回答了几个方向:一是重采样,做过采样或者欠采样;二是修改损失函数,比如给少数类样本分配更高的权重,或者用Focal Loss;三是用异常检测的思路处理,当成单类分类问题;四是评估时改用PR曲线和AUC这些对不平衡不敏感的指标。这个问题的回答尽量体现出你有实际处理过,而不是只会背名词。
3.4 大模型与前沿方向:Attention、Transformer、蒸馏与量化
算法岗实习面试已经绕不开大模型了,尤其是一些做AI平台或者应用型团队,会直接问你对大模型训练和推理的理解。我面试中遇到的一个有代表性的问题是:训练一个LLM大概包括哪些阶段,以及每个阶段在干什么。经典的答案是预训练、监督微调SFT、基于人类反馈的强化学习RLHF或DPO、推理部署这几个阶段。虽然是八股,但每个阶段后面都能展开很多细节,面试官如果感兴趣会一直往下追问。
还有一次被问到知识蒸馏的原理。我的回答是,用一个大模型或教师模型去指导一个小模型或学生模型,让学生模型拟合教师模型的输出分布,而非硬标签,这样能学到教师模型在类别间模糊关系上的软信息,使得小模型在保持推理速度的同时逼近大模型的效果。面试官追问了蒸馏的温度参数怎么设置,这要从softmax的软化效果来回答,温度越高,输出分布越平滑,软化程度越高,携带的相对关系信息也越丰富。
参数量评估、模型量化和推理加速这些内容也有被问到。量化这块,我简单回答过把FP16或者FP32的权重用INT8表示,减少显存占用,加快推理速度,但同时可能会掉点,需要用校准数据做量化感知训练或训练后量化。我对这个方向了解不深,面试时表达得比较保守,也主动说了自己目前还在学习阶段,面试官没有继续深挖。
4. 项目经历面试细节:少讲模型,多讲思考和取舍
项目环节是很多简历上没有实习经历的本科生的救命稻草。但也正是这一环,最容易暴露问题。我的经验是,项目讲解的套路其实是可以设计的,而且一定要从“解决什么问题”出发,而不是从“我用了哪些模型”出发。
4.1 怎么讲项目才能不露怯
我自己的项目讲法分成四步:背景、问题、方案、结果。背景是说这个项目解决什么场景下的什么问题,比如推荐系统是给用户推荐可能感兴趣的物品,文本分类是把客服消息自动分成几个大类。问题是指在这个场景下真正棘手的是什么,比如数据稀疏、类别不均衡、冷启动怎么解决。方案部分要讲清楚你用了什么方法以及为什么选这个方法,这里一定要解释“为什么”,这是面试官最看重的部分,可以说数据量小所以选了轻量模型,或者线上有延迟要求所以要控制特征数量和模型复杂度。结果部分要给出可量化的指标,比如准确率提升了多少,响应时间降到多少,或者和哪些baseline比较过。
我当时讲推荐系统项目的时候,面试官追问的问题是:协同过滤和矩阵分解的区别是什么,你的方案里为什么没直接用深度学习模型。这两个问题恰好都是我的思考盲区,之前我更多是照着一篇开源方案复现,没有仔细推敲过背后的取舍。后来我补了课:协同过滤直接使用用户物品交互矩阵计算相似度,矩阵分解则是把交互矩阵分解成用户和物品的低维隐向量,利用隐向量内积来预测,泛化性更强,冷启动问题依然存在但可以通过内容特征辅助缓解。至于为什么不用深度学习模型,要从数据量和可解释性两个角度回答,数据规模不足时复杂模型容易过拟合,而且工业界很多场景对可解释性有强需求。
4.2 面试官最爱追问的几个“坑”
项目环节最容易被追问的有几类问题:数据从哪里来、数据量多大、特征怎么构造、模型结构是什么、超参怎么调的、评估指标为什么选这个、有没有线下线上不一致的问题。这些问题其实都是考察你是不是真的做过项目,而不是背了个demo。
其中“特征怎么构造”是最容易被问到的。我的经验是,要讲清楚特征的类型和它对应的业务含义,比如用户历史行为序列特征、时间衰减特征、交叉特征。如果讲师说“我用了一个embedding”,面试官很可能追问embedding是怎么训练出来的、维度怎么确定的、冷启动怎么解决。我当时被问到“embedding维度怎么确定”时确实楞了一下,因为我只是照搬了论文里的64维,没有想过去验证。后来我补了一课,理解到embedding维度本质上是一个超参,和词表大小、样本量、任务复杂度都有关,可以先从较小的维度开始,通过验证集效果来调整,不必盲目追求大维度。
“有没有做过A/B测试”也是高频问题。如果项目只是离线实验,就得坦诚说明离线评估和线上真实效果的差异,同时可以提一下如果上线会怎么设计实验,包括流量划分、实验周期、显著性检验这些。这个问题我没法造假,就老实说没有上线条件,但给出了一个实验方案,面试官也表示认可。
4.3 弱校本科生没有实习经历要怎么包装项目
包装这个词听起来有点贬义,但其实不是让你造假,而是把已有的经历用更好的方式呈现出来。如果没有实习经历,就尽量自己做一两个完整项目,项目不一定要多高级,关键是闭环:数据获取、数据清洗、特征工程、模型训练、评估、分析思考,全套走完。哪怕用的都是公开数据集,也能证明你有独立做事情的能力。
在简历上,项目部分不需要写太多废话,突出你做的事情和量化结果就行。我见过很多简历写“负责xx系统的开发”,没有结果也没有细节,这种描述在筛选阶段几乎等于没有。好的写法是“基于xx数据集,设计xx特征,实现xx模型,将准确率从88%提升到92%,并通过xx方法解决了类别不均衡问题”,一眼看过去就有画面感。
面试的时候,还可以主动把项目往职位方向上靠。比如面的是搜索推荐方向的算法岗,就多讲推荐系统项目里的排序、召回、用户行为建模细节。面的是大模型应用方向,就多讲文本处理、Prompt设计、模型微调相关的内容。方向匹配度在面试里是隐形的加分项。
5. 面试流程复盘:从一面到HR面,每轮在考什么
春招实习的流程大体都差不多,简历筛选、技术一面、技术二面、HR面,有些公司还会有笔试和加面。我这里按我经历的流程环节,把每一轮的特点和考察重点说一下,大家可以根据这个框架来调整自己的准备重心。
5.1 技术一面:基础与项目为主,算法题为辅
技术一面通常是未来和你同团队的工程师或者技术骨干来面,考察的重点是基础能力和项目真实性。我当时的一面绝大多数是从两三个基础题开始的,比如问讲一下HashMap的实现原理、TCP三次握手为什么是三次、进程和线程的区别。这些是计算机基础,算法岗也躲不掉,所以复习的时候别只盯着算法和机器学习,计算机网络、操作系统、数据库的基础也是要过一遍的。
一面里项目环节占的比重比较大,面试官会非常仔细地追问项目里的细节,力求确认这个东西确实是你自己做的。除了项目,一面还喜欢问一道中等难度的算法题或者机器学习基础题。我遇到的一道题是实现一个LRU缓存,这是经典题目,用哈希表加双向链表实现,面试官还追问了为什么用双向链表而不是数组。另一个我印象深刻的题是给我一个场景,让我设计一个推荐策略,这已经是偏方案设计的题目了,需要从召回、粗排、精排、重排的链路里选一部分来讲。
5.2 技术二面:方案设计、发散思维与底层原理
二面一般是团队负责人或者更资深的人来面,侧重点会从“会不会”转向“能不能做事情”。二面的问题更开放,比如“如果给你一个大规模文本数据集,你会怎么构建一个分类系统”“对于新上线的特征,你怎么评估它有没有效果”。这类问题没有标准答案,考察的是解决问题的思路。我当时遇到的一个问题是:如果推荐系统里物品发生冷启动,除了基于内容的方法,还能怎么做。我回答了利用用户行为序列构造伪交互、利用图神经网络做热启动传播、以及用探索策略把新物品曝光给部分用户拿到反馈后再介入。面试官没有说这个答案“对”或“错”,反而顺着我的思路继续聊了下去,这让我感觉到,二面更像是在看你适不适合在这个团队工作。
二面还喜欢问底层原理。比如问过Transformer里的Layer Normalization为什么比Batch Normalization更常用,尤其是序列长度经常变化的时候。回答时要讲清楚BN在batch维度上统计均值和方差,序列变长变短或者batch较小时统计不稳定;LN则在单样本内部做归一化,和序列长度无关,所以更稳定。这个答对了之后,面试官明显对我深入原理的态度比较认可。
5.3 HR面:谈薪、意愿与稳定性
HR面虽然不像技术面那么硬核,但翻车概率也不低。HR面主要考察的是求职意愿、沟通能力、稳定性,以及你对公司和团队是否有基本了解。有一个问题几乎必问:你还投了哪些公司,目前进展怎么样。这个问题回答要有策略,既不能只说“只投了你们一家”,显得没有竞争力,也不能高调地把自己说成offer收割机,显得随时会跑路。比较稳妥的说法是“还有两三家在进行中,但贵司是我很倾向的方向”,然后再具体说为什么倾向。
另一个HR常问的问题是“你的职业规划是什么”。这个问题我一开始回答得比较大而空,被HR继续追问“具体到两年内你希望达到什么水平”之后才意识到,人家问的不是宏大理想,而是你对自己的定位有没有想清楚。后来我的回答变成了:两年内先把算法的落地流程走通,熟悉特征工程、模型训练、上线部署、评估迭代的整个闭环,能独立负责一个子方向的迭代优化。这样听起来就更具体、更可信。
HR面还会问一些压力测试问题,比如“你觉得你最大的缺点是什么”“如果导师布置的任务很重,你怎么平衡”。这类问题建议提前准备几个合适的答案,核心是真实而不致命,并且要给出改进的行动方向,不要让面试官觉得你止步于自我批评。
5.4 笔试与在线测评准备要点
春招笔试有相当一部分是在线编程题,模式通常是在牛客网或者公司自己的平台。我的经验是,在线笔试比面试手撕代码更考验熟练度,因为时间是连续的,题目数量多,你不能在一道题上磨太久。笔试前最好提前熟悉平台的操作方式,比如输入输出的读取方式、有没有代码自动补全、能不能编译调试,这些看起来不起眼的细节,在考场上能省下很多时间。
笔试题目里,贪心、二分、动态规划、图论、字符串这几种类型出现频率很高。我的做题策略是:先扫一遍所有题目的难度,把自己最有把握的题先做完,拿到保底分,再回头啃难题。不要在一道题上花超过20分钟,做不出来先跳过,把能拿的分全部拿到才是笔试的核心目标。有些公司笔试里还会有选择题,考察机器学习基础、操作系统、网络等基础知识,这部分需要平时积累,短时间突击效果有限。
6. 常见问题与复盘技巧:我在春招里踩过的坑
最后这部分,我整理一些自己在春招过程中踩过的坑和总结出来的经验,不一定是面试题本身,但都很关键,希望你们不用再走一遍。
6.1 简历投递策略:海投还是精准投
我的经历是,第一波投递特别盲目,看到算法岗就投,结果很多简历石沉大海。后来复盘才发现,我没有把简历里的关键词和岗位要求对齐。比如有些岗位明确要求熟悉推荐系统,我就应该把推荐系统项目放在前面,并且突出相关的技术点。所有投递的岗位都共用一份简历,这其实是个误区,至少应该准备几份不同侧重点的版本,针对不同的岗位方向做调整。
投递渠道方面,除了常规的招聘网站和公司官网,找内推比海投效率高不少。内推可以让简历更快被看到,也让你有机会提前了解团队在做的事情。我第一轮没有找内推,吃了很多闭门羹,后来通过学长和论坛找到了一些内推码和微信渠道,面试机会明显变多了。如果你不认识任何内推渠道,也可以直接去开源社区里找一些公司的员工分享的技术文章,评论区往往能找到联系方式。
6.2 面试时间安排:不要在同一周堆太多的面试
我开始面试的时候犯了一个错误,就是把自己能约的所有面试都挤在一周内,结果前几场因为紧张表现不佳,面完之后又没时间复盘,后几场还在犯同样的错误。我的建议是,如果面试时间可以自己约,尽量隔开一到两天,每次面试完留出足够的复盘时间。复盘不要只记录题目,要把“我哪里答得不好”“面试官为什么追问这个”“如果再来一次我会怎么回答”都写下来,这些才是真正能让你成长的东西。
有一些面试会和笔试冲突,需要做好优先级选择。我当时的原则是,已经进展到面试流程的公司优先,笔试时间可以尝试申请调整;如果实在冲突,就把精力放在进度更接近拿offer的那个流程上。毕竟春招窗口有限,把时间花在最接近成功的地方,收益才最大。
6.3 心态管理:被挂是常态,复盘才是关键
算法岗的面试,尤其是弱校本背景,被挂是大概率事件。我统计了一下,自己春招期间投了四五十份简历,进面试的可能只有十分之一,面试通过率也不高。这里面的原因很多,有背景筛选的因素,也有自己准备不足的因素,但最忌讳的就是因为被挂就自我否定。
我分享一个对我很有帮助的做法:把每场面试都当成一次免费的一对一辅导。面试官愿意花半小时到一个小时来和我聊天,指出我知识体系里的漏洞,这其实是一种很高效的学习方式。被挂了之后,我会重点复盘那些答不上来的问题,把它们彻底搞懂,争取下一场面试遇到同类问题能回答得更完整。抱着这种心态,我后来的面试状态反而越来越松弛,通过率也慢慢上来了。
6.4 经典面试题速查表
为了让大家方便自测,我把春招里高频出现的一些问题做成了表格形式,大家可以拿来自查,看看哪些能流畅地答出来,哪些还需要补课。不要只背答案,试着说出背后的“为什么”。
| 分类 | 高频问题 | 考察点 |
|---|---|---|
| 基础算法 | 快排原理、退化情况和优化方法 | 复杂度分析和实际编码能力 |
| 基础算法 | KMP的next数组怎么写,如何优化 | 字符串匹配原理,边界条件处理 |
| 数据结构 | LRU缓存怎么实现 | 哈希表+双向链表的设计能力 |
| 数据结构 | 二叉树最近公共祖先的几种解法 | 递归与倍增思想 |
| 动态规划 | 最长递增子序列的两类解法 | 状态设计与优化意识 |
| 机器学习 | XGBoost相对GBDT的改进 | 二阶梯度、正则化、并行化理解 |
| 机器学习 | 逻辑回归为什么用交叉熵损失 | 梯度特性与优化原理 |
| 深度学习 | ReLU的优缺点及缓解方案 | 激活函数对训练过程的影响 |
| 深度学习 | Transformer为什么需要位置编码 | Self-Attention的结构性缺陷 |
| 项目 | 特征是怎么构造的,为什么这么构造 | 业务理解与特征工程能力 |
| 项目 | 为什么不用更复杂的模型 | 场景约束与方案权衡意识 |
| HR面 | 还投了哪些公司,进度如何 | 意愿和稳定性评估 |
6.5 复盘笔记怎么记才有价值
最后分享一个我觉得很重要的习惯,就是复盘笔记一定要按照“问题、回答、改进”三个维度去记,而不是简单地记录题目内容。我在春招期间的复盘笔记格式大致是这样的:问题是什么,我当时是怎么回答的,面试官的反馈是什么,我后来查资料得到的标准答案或更好的答法是什么。把这三个维度填清楚,一篇笔记才有复用的价值。我是用Markdown文档来维护这份复习笔记的,按公司和面试时间分了目录,每周会在面试结束后的晚上统一整理,不会拖到第二天。
说实话,这些笔记到最后面试结束也没有全部复习完,但整理笔记本身的过程就是一次深度复习。写到这里的很多东西,比如KMP的nextval优化、Dijkstra为什么不能处理负权、LN和BN的适用场景,我都是在复盘过程中才真正搞明白的。如果有人问我要一份面经,我觉得分享复盘笔记比分享面试题目列表更有用,因为面试题目是死的,但复盘思路是可以复用的。
最后说一点体会。弱校本科生找算法岗实习,难吗?难。但回头看,这个过程中真正让我成长的并不是拿到了哪个offer,而是自己把一个一个知识盲区补齐、把一场一场面试打下来的过程。如果你也在走这条路,希望这篇文章能帮你少走一点弯路,也希望你能在春招里等到适合自己的那个机会。