
2020年秋招那阵子我正在集中投AI算法岗第四范式是我比较早收到笔试通知的一家。当时对这家公司的印象是“做AutoML和机器学习平台很出名”去翻了一下往年笔经信息不多只看到有人提到题目偏工程和数学整体风格比较硬核。真正坐到笔试系统前面我才发现这套题和互联网大厂常见的“八股文LeetCode”套路区别不小有些题甚至带着明显的业务建模倾向。这篇文章把第四范式2020秋招笔试里我印象比较深的题目、踩过的坑和复盘思路整理出来。虽然每年题目都会变但这家公司的出题方向和考察重点有比较强的延续性对准备通用AI算法岗笔试也有参考价值。如果你正在准备类似的企业笔试建议把重点放在机器学习原理的推导能力、特征工程敏感度以及手写代码的边界处理能力上而不是死刷LeetCode。1. 整体考情与题型设计思路拆解1.1 第四范式笔试题的整体印象先说整体结构。2020年第四范式秋招的笔试时间是90分钟系统是牛客网。题量不算大我记得大概是10道不定项选择题、3道编程题没有单独的大题来手推公式但选择题里对公式细节的考察很细细到你可能觉得“这也要考”。整张卷子给我的第一感觉是它不是单纯考你会不会写代码而是考你有没有真正理解机器学习模型在干什么。选择题部分涉及大量模型原理、损失函数、评价指标、特征工程、概率统计的内容编程题则集中在数据结构和算法难度中等偏上但也有几道题需要在思路上绕一下。“IEG”这个考试模块代码在这里指的是笔试系统中的题组分类主要对应机器学习与算法综合能力测试。某些年份也可能被标成别的模块代码但本质相同考察候选人在算法、模型、数据三个维度上的综合能力。1.2 为什么这家公司要这样设计笔试我看过一些第四范式的招聘JD核心岗位是算法工程师和机器学习平台开发工程师。这类岗位日常面对的是给企业客户搭建AI模型、做特征工程、调参、优化推理性能。所以笔试不太可能只考背诵式知识点更看重候选人的“建模直觉”。举个例子选择题里有一道关于逻辑回归与线性回归区别的题乍一看是基础题。但它给的选项不是简单的“一个用于分类、一个用于回归”而是把损失函数、参数更新方式、决策边界甚至特征归一化的影响都混在一起。如果你只是知道逻辑回归是“在线性回归外面套了个sigmoid”这道题很容易蒙。这背后的出题逻辑很清楚公司希望招到的人不是只会调包调参而是能理解模型从输入到输出的完整链路。也就是说当模型效果不好时你要知道问题出在数据、特征、模型还是训练过程。笔试只是第一道筛子但它已经把“只会调包的人”和“理解模型的人”区分开了一部分。另外编程题部分没有出特别偏门的题目基本是经典算法的变形。2. 高频考点与核心知识解析这些知识点必须真正吃透2.1 机器学习基础从推导到应用的全面考察第四范式笔试的选择题里机器学习基础占比非常高大概覆盖了一半左右的题目。我印象比较深的几个方向损失函数与优化交叉熵、均方误差、Hinge Loss的区别和适用场景梯度下降、随机梯度下降、小批量梯度下降的收敛特性差异。正则化L1和L2的区别、为什么L1能产生稀疏解、两者在贝叶斯视角下分别对应什么先验。模型复杂度与偏差方差过拟合的典型表现、交叉验证的正确使用方式。树模型与集成学习决策树的划分依据信息增益、增益率、基尼指数、随机森林与GBDT的差异、XGBoost的近似分裂算法思路。聚类与降维K-Means的初始点选择问题、PCA的数学原理是什么、t-SNE的适用场景限制。评价指标精确率、召回率、F1、AUC的计算与含义特别是样本不均衡时的选择逻辑。你会注意到这些考点并不是相互独立的。比如逻辑回归这道题如果你能理解逻辑回归的损失函数是交叉熵就自然能理解为什么它比线性回归的平方损失更适合分类任务也就能理解为什么梯度更新形式会不同。这种“知识点串在一起”的考察方式是第四范式笔试的一个显著特点。所以我的建议是复习时不要只背结论要把每个知识点的“为什么”搞明白。你不需要像数学系学生那样能把所有公式从头推一遍但至少要知道推导的关键步骤和每个公式的直觉含义。2.2 概率统计与数学基础容易被忽视的隐形考点第四范式笔试里概率统计的占比明显高于一般的互联网公司笔试。这其实符合AI岗位的特点因为大量模型都是基于概率框架的。选择题里出现过一个经典问题已知某事件发生的概率为p独立重复n次求至少发生一次的概率。这个题本身不难答案是1-(1-p)^n但它换了个包装将“事件”替换成“模型训练中某次迭代随机丢失特征”让你在多个选项里挑出正确的概率表达式。这样一来简单考点就变成了对场景的理解题。另一个印象比较深的题是求期望。题目大意是有n个样本每个样本以一定概率被选入训练集问训练集中样本数量的期望和方差。这实际上是二项分布的应用但如果你只背了二项分布的公式而不知道它什么时候适用看到“以一定概率”这种描述时可能会卡壳。数学基础方面线性代数中的矩阵求导、特征值分解微积分中的偏导数计算也时常以选择题或编程题前置知识的形式出现。比如有一道选择题问给定一个二次型矩阵判断它是否正定。这看起来是纯数学题但背后关联的是损失函数是否凸、优化能否收敛的问题。给我的教训是复习AI笔试时不要只盯着机器学习模型概率论、线性代数、微积分这些数学基础要同步复刷。2.3 数据结构与算法刷题之外还要注重边界处理编程题部分2020年第四范式秋招给我的感觉是题目的算法模型不复杂但边界条件非常容易出错。你只要能想到正确的算法写出来并不难但如果你在边界条件上少考虑了某种情况很可能只能通过部分测试用例。这三道编程题我复盘后认为分别对应了双指针或哈希表、动态规划、图或并查集。具体的题目细节我不方便完整贴出毕竟不是官方公开题而且记住的也只是大意但我会在下一部分给出还原后的模拟题以及完整的解题思路这对你想了解面试风格更有帮助。3. 笔试实操手撕三道模拟题完整复盘3.1 最长连续序列变形双指针与哈希表模拟题大意给定一个未排序的整数数组找出其中最长连续序列的长度。要求时间复杂度控制在O(n)。看到这道题很多人的第一反应是先排序再遍历。但排序的时间复杂度是O(n log n)不符合要求。正确思路是使用哈希表先把所有数字放入一个集合然后遍历每个数字只有当它是某个连续序列的起点时才向后扩展。什么叫“是连续序列的起点”就是num-1不在集合中。这个判断很关键可以避免重复扩展同一个序列。我写的参考代码如下def longest_consecutive(nums): num_set set(nums) max_len 0 for num in nums: if num - 1 not in num_set: cur num cur_len 1 while cur 1 in num_set: cur 1 cur_len 1 max_len max(max_len, cur_len) return max_len这道题的代码量不大但有两个容易踩的坑重复元素的处理如果不先转成集合重复数字会导致同一个序列被多次统计。起点判断的漏写如果不加num - 1 not in num_set这个判断时间复杂度会退化到O(n²)在牛客网的极端测试用例下一定超时。这题原版的LeetCode编号是128但笔试里会稍微变形比如把“连续序列”改成“间隔为1的序列”或者要求返回序列本身而不是长度。无论怎么变核心都是“用集合去重只用起点做扩展”。3.2 编辑距离变体动态规划的经典应用模拟题大意给定两个字符串A和B每次操作可以插入、删除或替换一个字符求将A变成B的最少操作次数。编辑距离是动态规划的经典题。状态定义非常直接dp[i][j]表示A的前i个字符变成B的前j个字符所需的最少操作次数。转移方程分两种情况如果A[i-1] B[j-1]则dp[i][j] dp[i-1][j-1]否则dp[i][j] min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) 1分别对应删除、插入、替换参考代码如下def min_distance(a, b): m, n len(a), len(b) dp [[0] * (n 1) for _ in range(m 1)] for i in range(m 1): dp[i][0] i for j in range(n 1): dp[0][j] j for i in range(1, m 1): for j in range(1, n 1): if a[i - 1] b[j - 1]: dp[i][j] dp[i - 1][j - 1] else: dp[i][j] min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) 1 return dp[m][n]我笔试时在这道题上犯了一个低级错误初始化的循环写成了从0到m-1结果边界条件全错了。动态规划的题目初始化那两行是最容易出问题的地方。你可以在开始写代码前先把dp表格在纸上画出来明确dp[0][j]和dp[i][0]的含义再动手写。笔试时它还加了一个小变化要求输出具体的最短编辑方案而不只是操作次数。这就需要在填dp表的同时维护一个路径数组最后倒推回去。难度会高一些但核心还是同一个状态转移方程。3.3 朋友圈数量扩展并查集或DFS/BFS模拟题大意给定一个n×n的矩阵MM[i][j]1表示第i个人和第j个人是朋友朋友关系具有传递性即朋友的朋友也是朋友求朋友圈的总数。这道题既可以用并查集也可以用DFS/BFS染色。我当时用的是并查集因为实现起来逻辑清楚而且能处理动态添加关系的扩展场景。并查集的参考代码如下def find(parent, x): while parent[x] ! x: parent[x] parent[parent[x]] x parent[x] return x def union(parent, rank, x, y): root_x find(parent, x) root_y find(parent, y) if root_x ! root_y: if rank[root_x] rank[root_y]: root_x, root_y root_y, root_x parent[root_y] root_x if rank[root_x] rank[root_y]: rank[root_x] 1 def circle_num(M): n len(M) parent list(range(n)) rank [0] * n for i in range(n): for j in range(i 1, n): if M[i][j] 1: union(parent, rank, i, j) return len({find(parent, i) for i in range(n)})这道题的坑在于如果你用DFS染色要确保对每个未访问节点都启动一次DFS否则会漏掉不连通的分量。如果你用并查集要注意路径压缩的写法否则在大规模输入下会超时。另外一类变形是“求连通块的最大面积”或“求连通块的平均大小”思路类似只需要在遍历时额外计数。4. 常见问题与排查技巧实录4.1 时间分配选择题竟然比编程题更耗时间我笔试时犯的一个明显策略错误是在选择题上花的时间太长。原因是很多选择题不是“一眼看出答案”的基础题而是需要推一下、算一下甚至排除一下的“小计算题”。我在某道概率题上至少花了5分钟直接压缩了后面编程题的思考时间。复盘后我认为正确的策略应该是这样的先做编程题用20-30分钟把三道编程题全部写完哪怕有些边界条件没想清楚也先提交一个基础版本保底。再回头做选择题选择题虽然分值不低但单题耗时不应该超过2分钟。如果卡住了先凭直觉选一个并标记最后有时间再回来细算。这里的逻辑是编程题只要通过了测试用例分数就是确定的而选择题哪怕是蒙的也有概率得分。把时间优先投入到能稳定拿分的题目上是笔试的基本策略。4.2 编程题的边界条件看似简单实则致命我身边有个朋友也参加了同一年的笔试他出来后吐槽第二题编辑距离的思路完全正确但只通过了70%的测试用例。后来我们对比了一下发现他的代码在其中一个字符串为空时没有正确初始化边界值导致返回结果始终为0。这种问题在LeetCode上其实不容易暴露因为LeetCode的测试用例相对温和。但笔试系统里的测试用例覆盖更全面空数组、超大数、单元素数组、字符串包含空格、负值等边界情况都会出现。所以在提交代码前我建议你养成一个习惯在脑子里至少跑三个测试用例空输入或长度为1的输入所有元素相同或全部不同的极值情况大规模输入可以用最大数据量估算运行时间是否在限制内这几个用例能帮你发现大部分边界问题。4.3 多选题的“宁缺毋滥”原则第四范式的选择题里有一批是不定项选择而且明确说明“少选得部分分多选不得分”。这意味着如果你对一个选项没有把握干脆就别选它。我个人的经验是多选题先圈定两个绝对确定的选项其他选项即使看起来很像正确答案只要有一丝犹豫就不选。部分分值也比零分强。还有一个技巧是利用选项之间的关联来推理。比如有一个选项是“L1正则化等价于给参数加上拉普拉斯先验”另一个选项是“L2正则化等价于给参数加上高斯先验”这两个通常是捆绑出现的。如果你能确定其中一个是错的另一个大概率也不该选。4.4 考前如何针对性准备如果你打算投第四范式的算法岗我的建议是机器学习基础把李航的《统计学习方法》前八章认真看一遍尤其是逻辑回归、SVM、决策树、集成学习公式要自己推导一遍。概率统计把茆诗松的《概率论与数理统计》中的常见分布、期望方差、条件概率、贝叶斯公式复习一遍。编程题把LeetCode上动态规划、并查集、双指针、哈希表四类题目刷熟。不用追求刷题数量但要把每道题目的“为什么这样做”想明白。特征工程与业务场景这一点容易被忽略。第四范式的业务和AutoML密切相关笔试中可能出现“给定一个业务场景选择最合适的特征处理方式”这种类型的题目。多了解一些特征工程实操案例会让你更有把握。5. 写在最后一些关于秋招笔试的个人体会回头来看第四范式2020秋招的这套笔试题难度在当年AI岗笔试里属于中上水平但它比很多公司更聚焦在“机器学习算法”本身而不是广撒网式地考一堆无关的计算机基础。这其实是一个很好的信号说明这家公司对算法岗位的能力模型有清晰的定义。如果你正在准备类似的笔试我的核心建议只有一句话不要只刷题要把每个知识点背后的原理搞懂。笔试看得见的是做题能力看不见的是对知识体系的掌握程度。那些选择题的选项里藏着的全是平时学习时容易含糊过去的细节。最后说一个小技巧笔试完成后不管自我感觉好坏趁记忆还热乎的时候把题目和你的答案快速记下来。这套题会在你后续复盘时变成非常重要的参考材料。我上文整理的很多细节就是靠当时随手记的草稿回忆出来的。祝大家笔试顺利拿到心仪的面试机会。