十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

网易2018校招机器学习算法工程师笔试题全面拆解与备考指南

网易2018校招机器学习算法工程师笔试题全面拆解与备考指南 网易2018校园招聘机器学习算法工程师笔试卷这个标题在当年牛客网和各大技术社区里流传很广。我印象很深那一年算法岗的竞争已经明显升温机器学习、算法这两大关键词几乎成了筛选简历的硬门槛。这张卷子之所以被反复讨论是因为它的题型结构很典型客观题覆盖机器学习理论、数据结构与算法基础编程题考察工程实现能力整体难度对校招生来说不算友善但也没有离谱到劝退。这篇文章我想以亲历者的视角把这张卷子背后的命题逻辑、核心考点和备考思路完整拆一遍顺便把一些常见误区讲清楚。适合正在准备校招的应届生、打算跳槽算法岗的工程师以及想提前了解大厂笔试题型的学生参考。看懂这张卷子想考察什么比盲目刷题重要得多。1. 这张卷子到底在考什么整体设计与考察思路1.1 从2018年网易校招说起机器学习算法岗笔试题型的整体面貌2018年的校招时间线拉得很长内推批通常在7月就启动正式批在8月底到9月集中笔试网易属于动作比较快的那一批。机器学习算法工程师的笔试和纯后端开发、数据挖掘的笔试题型有明显区别。后端岗喜欢考操作系统、网络、数据库数据挖掘岗会掺入一些SQL和特征工程而机器学习算法岗的卷子几乎完全围绕机器学习理论、算法与数据结构展开偶尔会放一两道概率统计的题目。网易这份卷子的大致结构我记得是客观题加编程题。客观题包括单选题和多选题覆盖的范围很大从线性回归、逻辑回归、SVM、决策树这些经典模型到聚类、降维、模型评估、过拟合处理再到几个关键算法的推导细节。编程题一般是两道三道难度梯度拉开第一道通常是基础题后面会有需要优化复杂度的题比如用动态规划、贪心或者二分去解。整体给人的感觉是它不要求你掌握某个前沿模型而是考察基础是否扎实、思维是否敏锐。有一个容易被忽略的点网易的算法岗笔试卷里机器学习理论题目的比重通常比纯算法题更高。比如特征工程、正则化、偏差方差权衡这类问题基本年年出现。这说明出题人更关注候选人对机器学习本质的理解而不是单纯会调包。1.2 考点结构拆解客观题、编程题与综合题的比例和意图我梳理了2018年前后几家大厂算法岗笔试题的考点分布网易的特点在于“广度优先、深度跟进”。它不会像某些公司那样直接上特别偏门的模型细节而是先铺开问一堆基础题把知识点覆盖面拉满再用编程题去卡区分度。从比例上看客观题大约能占到整张卷子分值的50%到60%剩下的是编程题。客观题里可以粗略分成三类。第一类是“概念判断题”比如“关于SVM的核函数下列说法正确的是”“L1正则化为什么会产生稀疏解”这类题考察你是否真正理解原理。第二类是“公式推导与计算题”比如给定一个逻辑回归的损失函数要求推导梯度或判断某步更新是否正确。第三类是“场景应用题”比如“在类别不平衡时以下哪种评估指标更合适”这类题考察你在真实数据环境下的判断力。编程题则更直接基本就是算法题。常见的是数组、字符串、链表、树、动态规划、贪心、搜索这些类别。网易相对重视分治和动态规划因为这两类算法和机器学习里的许多优化思想是相通的。比如很多递归模型参数的求解底层就是动态规划思想。1.3 为什么这些考点决定你能否进面试笔试的作用不是选出代码写得好的人而是筛掉基础不牢、思维不清晰的人。面试官没有时间在面试里逐项确认你是否了解SVM的对偶问题所以笔试题承担了这个工作。机器学习算法工程师的日常工作比如特征处理、模型调优、分布式训练表面上看和笔试内容没有直接关系但底层能力是完全相同的。举个例子你在调XGBoost的时候如果理解CART树如何做分裂、信息增益如何计算就知道max_depth和min_child_weight应该怎么调而不是靠网格搜索瞎试。再比如当你需要手写一个简单的推荐召回算法时K-Means的收敛性和初始化敏感性如果理解不到位线上效果就会很差。笔试考这些内容本质上是考察你有没有构建起完整的知识体系。网易在这方面的筛选意图非常明显他们想招的不是会跑实验的人而是能从第一性原理出发解决问题的人。2. 算法与数据结构考点深度拆解从KMP到排序家族2.1 KMP算法与next数组一道真题的完整推导KMP算法几乎每年都会出现在大厂笔试中。网易2018年这道题就是在KMP的next数组上做文章题目形式一般是这样给定模式串Pabacaba求其next数组。别看题目简单出错率极高因为很多同学对next数组的定义和计算方式记忆是模糊的。先说next数组是什么。KMP算法的核心思想是当主串和模式串在某一位失配时模式串不一定要回到开头重新匹配而是根据已经匹配的部分跳到某个位置继续这个跳转的依据就是next数组。next[i]通常定义为模式串P[0...i-1]这个子串中最长相等真前后缀的长度。注意是“真前后缀”也就是说不能取整个子串本身因为那样就没有跳转意义了。以Pabacaba为例我按从0下标开始的方式算一下。next[0]约定为-1表示第一个字符就失配时模式串整体右移一位。当i1时子串是a最长相等真前后缀长度为0所以next[1]0。当i2时子串是ab前缀a和后缀b不相等next[2]0。当i3时子串是aba前缀a和后缀a相等长度为1所以next[3]1。i4时子串是abac经过判断没有任何相等的前后缀next[4]0。i5时子串是abaca前缀a和后缀a相等next[5]1。i6时子串是abacab前缀ab和后缀ab相等长度为2next[6]2。i7时子串是abacaba最长相等真前后缀是aba长度为3于是next[7]3。所以按这种定义Pabacaba的next数组就是[-1, 0, 0, 1, 0, 1, 2, 3]。注意不同教材对next数组的定义略有差异有的把next[i]定义为P[0...i-1]的相等前后缀长度有的则定义为P[0...i]的还有的会整体加1。笔试时如果题目给了定义一定按题目的定义来否则很容易算错。KMP算法在笔试里还可能延伸出另一个考点给你主串和模式串问匹配过程中模式串会滑动几次。这其实就是把next数组求出来后模拟一遍匹配的过程。平时练的时候可以把求next的代码也背熟考试时能省下很多时间。2.2 排序算法家族从冒泡到堆排的复杂度与稳定性对照排序算法是笔试的常客网易考察的点不在“会不会写冒泡排序”而在于对排序算法家族的整体认识。常见问法包括哪些排序是稳定的哪些排序的时间复杂度是O(n log n)在什么场景下应该选哪种排序我直接给大家一张表这也是我当年复习时手写过的排序算法平均时间复杂度最坏时间复杂度空间复杂度稳定性冒泡排序O(n²)O(n²)O(1)稳定选择排序O(n²)O(n²)O(1)不稳定插入排序O(n²)O(n²)O(1)稳定希尔排序O(n^1.3)左右O(n²)O(1)不稳定归并排序O(n log n)O(n log n)O(n)稳定快速排序O(n log n)O(n²)O(log n)不稳定堆排序O(n log n)O(n log n)O(1)不稳定这张表值得反复看。笔试常考的不是“快速排序平均复杂度是多少”这种送分题而是“下列排序算法中哪些在平均情况下时间复杂度为O(n log n)且不稳定”这时候如果你只记住快排和归并的名字就很容易把归并的稳定性记错导致丢分。堆排序在很多资料里被单独拿出来考因为它的思想比较特殊把数组看成完全二叉树通过调整堆结构来获得最大或最小值。面试还喜欢追问“堆排序和快排实际用哪个”答案取决于场景。如果你需要稳定的排序选归并如果你对最坏情况非常敏感选堆排如果平时数据较随机且追求常数小选快排。STL里的sort就是混合了快排、插入排序和堆排序的introsort目的就是兼顾各种情况。2.3 贪心、动态规划与剪枝高频题型的出题逻辑程序员面试中有一句话动态规划是区分劳动者和思考者的试金石。网易笔试的编程题里动态规划和贪心几乎必考而且常常不会出太裸的题目而是把经典模型包装一下。贪心和动态规划的区别初学者经常搞混。贪心算法在每一步都做当前看起来最优的选择并且不回头它只能用于局部最优能推导出全局最优的问题典型例子是活动选择问题和哈夫曼编码。动态规划则把问题拆成重叠子问题记录中间状态通过状态转移方程得到最终结果典型例子是背包问题、最长公共子序列、编辑距离。笔试中容易设陷阱的点正是在这里。比如给你一组硬币面值和目标金额问最少需要几枚硬币凑出目标如果你直接用贪心在某些面值组合下会得到错误答案。题目如果设计成面值是1、5、11目标20贪心会得到1张11加9张1共10枚而正确答案是4张5共4枚。这个例子大家一定要记牢它是区分贪心和动态规划的经典案例。剪枝算法则更多出现在搜索题里。搜索题的暴力写法往往超时优化方向有两个一是用记忆化搜索也就是把递归过程中重复计算的中间状态存下来本质上是动态规划的递归写法二是剪枝也就是在搜索过程中提前判断后续分支不可能产生更优解直接跳过。比如在解数独或者N皇后问题时合理剪枝能指数级减少搜索空间这在大厂笔试的压轴题里经常用到。2.4 图算法与进阶优化算法Dijkstra到群体智能图算法在机器学习算法岗笔试试卷里出现的频率比很多人想象中要高。因为推荐系统、社交网络分析、路径规划这些业务场景都离不开图算法。网易考过的最基础也最经典的是Dijkstra算法考察点包括它适用于什么图非负权值、时间复杂度是多少用堆优化后是O(E log V)、为什么不能用负权边。除了DijkstraFloyd和Bellman-Ford也值得了解。Floyd适合全源最短路径复杂度O(V³)实现极其简单三重循环就完事。Bellman-Ford可以处理负权边代价是复杂度较高。如果笔试中看到题目的边权没有负数优先用堆优化的Dijkstra如果节点数量很小比如不超过200直接Floyd写起来最省事。热词里还出现了粒子群算法原理、模拟退火算法、PID算法、FOC算法、MPPT算法这些属于优化算法和控制算法的范畴。虽然它们不会直接出现在网易笔试题里但我在面试中确实被追问过粒子群和模拟退火的区别。机器学习里的超参数搜索比如随机搜索和贝叶斯优化的思想和粒子群算法就有相通之处。这类算法属于“面试加分项”有余力的同学可以了解大致的流程能说出它们和梯度下降的区别就足够了。3. 机器学习理论核心考点从原理推导到模型评估3.1 监督学习三件套线性模型、SVM与决策树机器学习理论部分线性模型永远是大头。线性回归的损失函数为什么选均方误差逻辑回归为什么用交叉熵而不是均方误差这两个问题几乎是必考题。逻辑回归用Sigmoid函数把线性输出映射到[0,1]区间用交叉熵作为损失函数是为了让优化目标变成凸函数梯度下降更容易收敛。如果换成均方误差损失函数非凸会出现很多局部极值点训练过程会非常痛苦。SVM是网易笔试的大户。常考的考点包括SVM的优化目标是什么、什么是支持向量、软间隔中的惩罚参数C起什么作用、核技巧的本质是什么。很多同学只知道SVM要找最大间隔超平面不理解为什么引入拉格朗日对偶。简单说对偶问题让内积运算可以通过核函数直接计算从而把低维线性不可分的问题映射到高维变得线性可分同时不对计算量造成指数级增长。决策树需要掌握ID3、C4.5和CART的区别。ID3用信息增益选择特征倾向选择取值多的特征容易过拟合。C4.5用信息增益比来修正这个偏差。CART则用基尼指数而且构建的树是二叉树。笔试里如果给一个简单数据集要求手动计算信息增益并选择最优划分特征这种题一定要会它考察的是对信息熵公式理解的扎实程度。3.2 无监督学习与聚类算法K-Means与层次聚类的原理盲区无监督学习在笔试里出题频率低于监督学习但K-Means基本年年出现。考点包括K-Means的步骤、如何选择K值、它对初始中心点是否敏感、如何评估聚类效果。K-Means的步骤其实很简单先随机选K个中心点然后迭代两步——把每个样本分到距离最近的中心点所属的簇然后重新计算每个簇的均值作为新的中心点直到中心点不再变化或变化很小。笔试容易挖的坑是问“K-Means一定能收敛到全局最优吗”答案是否定的它只能收敛到局部最优因此实际中常常需要多次随机初始化取效果最好的一次。K值选择常用肘部法则画出SSE随K变化的曲线找拐点。层次聚类也值得留意它不需要预先指定簇数而是逐步合并或分裂。笔试常考的是“凝聚式层次聚类的合并策略”包括单连接两个簇中最近点的距离、全连接最远点距离、平均连接平均距离。这类细节题比较冷门但一旦出现区分度很高因为大多数人复习时只关注了K-Means。3.3 模型评估与选择偏差方差、交叉验证与过拟合模型评估这块属于“看着简单、拿分不易”的部分。偏差方差分解是理论基础偏差衡量模型预测值与真实值的差距方差衡量模型在不同训练集上的波动程度。高偏差对应欠拟合高方差对应过拟合。笔试里的经典题是画一个偏差方差与模型复杂度的关系图或者问你“增大训练集样本数量会降低偏差还是方差”——答案是主要降低方差。交叉验证也必须掌握。K折交叉验证把训练集分成K份轮流拿其中一份做验证其余K-1份做训练最终结果取平均。它的优点是充分利用数据缺点是计算开销大。笔试容易考“K折交叉验证中K应该怎么取”一般K5或10比较常用。如果数据集类别不平衡还要注意分层采样保证每一折里类别比例与整体一致。过拟合的应对方法几乎是必考增加训练数据、简化模型、正则化、早停、Dropout、数据增强。L1正则化和L2正则化的区别也要能说清楚L1会让部分权重变为0产生稀疏解可以用作特征选择L2让权重都趋向于小值但不会为0它起到的是平滑作用。正则化系数lambda太小等于没加正则太大则会让模型偏差变大。3.4 优化方法与深度学习入门梯度下降、反向传播与常见网络深度学习在这个时期的笔试题里占比还不算太高但从2017年开始就呈现上升趋势。梯度下降的几种变体——批量梯度下降、随机梯度下降、小批量梯度下降——几乎是必考的送分题。要记住它们的区别批量梯度下降每次用全部数据计算梯度准确但慢随机梯度下降每次用一个样本快但有噪声小批量是折中方案深度学习里最常用。反向传播是深度学习面试的灵魂问题。笔试可能不会要求你完整推导链式法则但会考概念的组合比如“权重更新时误差对某一层的梯度是如何通过链式法则传递的”。至少要做到能画出简单的全连接网络结构并手动算出某一层的梯度。常见的网络结构需要了解卷积神经网络CNN的基本组成卷积层、池化层、全连接层。知道卷积核的作用是提取局部特征池化的作用是降采样和增大感受野。循环神经网络RNN需要了解它如何处理序列数据以及梯度消失的原因是反向传播过程中梯度的连乘效应而LSTM通过引入门控机制缓解了这个问题。热词里提到“机器学习奖励驱动”这其实就是强化学习的基本思想网易笔试偶尔会出选择题问强化学习的基本组成即状态、动作、奖励、策略了解即可。4. 编程题实战一道典型题目的完整复盘4.1 题目描述与思路分析网易的编程题风格偏实用不太会出现特别偏门的算法但会在经典题上做变形。这里我选取一道和“归并排序求逆序对”类似的题型来复盘因为它既考察了排序算法的理解又考察了分治和优化思维和网易2018年的出题风格高度一致。题目大意给定一个长度为n的数组求满足i小于j且a[i]大于a[j]的个数也就是逆序对的数量。n的范围是10的5次方。如果直接用两层循环暴力求解时间复杂度是O(n²)在n较大的情况下一定会超时。这道题的最佳解法是用归并排序的分治思想在合并两个有序子数组的过程中统计逆序对。思路是这样的把数组不断二分直到每个子数组只剩一个元素。在合并两个有序子数组时如果右半边的某一个元素小于左半边的当前元素说明它比左半边当前元素及其后面的所有元素都小这些元素在原数组里都排在它前面所以逆序对的数量要加上左半边剩余元素的个数。4.2 代码实现与复杂度分析C实现如下#include bits/stdc.h using namespace std; long long mergeSort(vectorint nums, vectorint tmp, int left, int right) { if (left right) return 0; int mid left (right - left) / 2; long long count 0; count mergeSort(nums, tmp, left, mid); count mergeSort(nums, tmp, mid 1, right); int i left, j mid 1, pos left; while (i mid j right) { if (nums[i] nums[j]) { tmp[pos] nums[i]; } else { tmp[pos] nums[j]; count (mid - i 1); } } while (i mid) tmp[pos] nums[i]; while (j right) tmp[pos] nums[j]; for (int k left; k right; k) nums[k] tmp[k]; return count; } int main() { int n; cin n; vectorint nums(n), tmp(n); for (int i 0; i n; i) cin nums[i]; long long result mergeSort(nums, tmp, 0, n - 1); cout result endl; return 0; }这段代码的要点在于统计部分的时机当nums[i]大于nums[j]时说明左半边从i到mid的所有元素都比nums[j]大因此逆序对数量增加mid-i1个。注意count要开long long因为n为10的5次方时逆序对数量最大接近n*(n-1)/2即约5乘以10的9次方int根本放不下。这个细节当年我就踩过坑。时间复杂度是O(n log n)空间复杂度是O(n)完全满足题目要求。这里用了一个临时数组tmp来辅助合并避免合并时频繁开辟新数组造成额外开销。4.3 边界条件与测试用例笔试做题时边界条件的处理是拿分的关键。这道题的边界条件主要有三个。第一数组长度为1时递归函数应直接返回0。第二数组已经有序时逆序对数量为0代码不会进入else分支。第三数组完全逆序时比如[5,4,3,2,1]逆序对数量是10代码应正确统计。我建议备考时养成一个习惯写完代码先自己在本地跑几个测试用例。首先是题目给的样例其次是全正序、全逆序、全部元素相同的数组以及最小规模n1。这样能快速暴露代码中隐藏的问题。比如你有没有在递归返回时把辅助数组的值拷贝回去如果没有下一次递归合并时用的就是未更新的数据结果必然错误。还有一个提高效率的小技巧笔试平台一般会给出部分测试用例的运行结果。如果你的代码通过了样例但超时首先要想到的是复杂度是否过高。如果是逆序对这道题凡是把时间复杂度写成O(n²)的基本不可能通过全部用例。遇到这种题第一时间往分治、堆、树状数组方向想。5. 常见问题与避坑指南5.1 备考阶段的三大错误倾向第一个错误倾向是“只刷题不看书”。很多同学准备算法岗笔试一上来就是刷LeetCode刷到200题就觉得够了。但机器学习理论部分如果底子不牢客观题几乎会丢一半分。笔试不只看你会不会写代码还看你对模型原理的理解是否深入。我当时复习时给自己定的规矩是每天算法题量控制在4到6道其余时间读理论笔记重点看损失函数推导、模型评估、正则化这些高频考点。第二个错误倾向是“只看不练”。机器学习理论光看书很容易产生“我懂了”的错觉。比如偏差方差那一节书本上几句话就讲完了但实际做题时你会发现题目经常把概念绕来绕去不亲手推导几遍根本分不清。我建议备考时准备一个笔记本把每个模型的关键公式推导一遍逻辑回归的梯度、SVM里拉格朗日函数的构造、决策树的信息增益计算都手写一遍效果会好很多。第三个错误倾向是“考试时死磕某一道题”。笔试时间有限编程题的分数往往不是平均分配的。如果你在某道题上卡了20分钟还没思路赶紧跳到下一道把能拿的分先拿到。客观题里遇到不会的先标记出来不要影响后面答题的节奏。5.2 考场上的时间分配与做题策略以大厂笔试常见的90分钟为例我建议的时间分配是客观题控制在35分钟以内剩下55分钟留给两道编程题。客观题里如果有那种一眼不会的公式推导题先跳过去把会做的做完再回来看。很多时候做完后面的题再回来思路反而打开了。编程题的做题顺序也有讲究。先读题理解题目的数据范围因为它决定了你能用什么复杂度的算法。如果n是10的5次方O(n²)基本没戏O(n log n)是及格线。如果n只有1000O(n²)也许也能过但不值得冒险。确认算法后先写暴力版本验证思路再按复杂度要求优化这是一个比较稳妥的策略。考场里另一个容易出问题的地方是输入输出。题目要求多组输入时不要只写单组逻辑。很多同学在本地IDE测得好好的一提交就报错多半是输入输出格式不对。读题时注意看题目给的示例输入和输出之间有没有多余的空格或换行这些细节都会影响判题结果。5.3 笔试后的复盘清单笔试结束不代表这件事就过去了。我强烈建议每做完一套题都按下面的清单复盘一遍。第一整理错题。把所有做错的客观题对应的知识点记下来比如“决策树C4.5和CART的区别”“SVM软间隔C参数的含义”。第二回顾编程题的思路。如果你某道题没有AC至少要看一下题解理解正确的思路是什么然后重新手写一遍保证自己能AC。第三记录时间节点。你在一道题上花了多久是超出预期还是提前完成这能帮助你在下次笔试中更合理地分配时间。复盘的意义在于形成“错题—知识点—再练习”的闭环。很多东西第一次做错很正常但同一类错误如果出现两次说明你的知识体系里有断层。笔试考的就是把这些人筛出来所以复盘越详细你离面试就越近。最后再分享一个小技巧。准备网易这类公司的笔试时建议去搜一下它历年真题的命题偏好。有的公司喜欢考动态规划有的喜欢考字符串处理有的在机器学习理论里特别关注贝叶斯和概率图模型。有针对性地补强短板比漫无目的地刷题高效得多。我当时就是在牛客网上把前几年的网易真题找出来一道一道研究才慢慢摸清了出题人的思路。这个内容后续还可以继续扩展比如把常考模型整理成一份速查表或者把笔试中常见的编程题分类整理成专题。如果你正在准备校招希望这份拆解能帮你在复习时少走一些弯路。
返回列表