尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

B站算法岗笔试复盘:KMP、KNN与粒子群等核心考点详解

B站算法岗笔试复盘:KMP、KNN与粒子群等核心考点详解 B站2019秋招技术岗算法第二套笔试题在当年算法岗求职圈子里流传得挺广。这套题没有刻意炫技而是很务实地考察了一个算法工程师的基本功数据结构、经典算法、机器学习基础、数学推导还有现场手写代码的规范性。说白了它不是那种“刷题背模板就能过”的卷子但也不是完全脱离实际的“脑筋急转弯”。我当时把这份题从头到尾复盘过几遍越看越觉得它值得拿出来仔细讲——尤其是第二套的题型分布和考察深度几乎能当成一份算法岗笔试的标准范本。这篇文章会围绕这套题的整体思路、高频考点、容易踩的坑以及针对性的备考方法逐一展开。无论你是准备校招的应届生还是想转行做算法的工程师哪怕只是单纯想检验一下自己的算法底子都能从里面找到可以实操的东西。1. 整体印象这套算法笔试题到底难在哪1.1 考题设计与岗位要求是挂钩的很多同学刷笔试的时候有个误区总以为大厂算法岗笔试就是比拼谁刷的 LeetCode 题多谁手速快。但 B 站这套题给我的第一感觉是它更想找到“能落地解决问题”的人而不是“背题机器”。题目里有不少经典算法题但更关键的是它会在基础算法之上加入工程化追问考察你知不知道这个算法在真实业务里该怎么用、复杂度怎么分析、边界怎么处理。比如字符串匹配、排序、图论这些看起来都是“老面孔”但实际作答时你会发现考的不只是写代码还包括对算法原理的准确表述。像 KMP 的 next 数组很多人刷题时会用模板但题目里特意定义 next[i] 的计算方式就是逼着你把原理讲清楚而不是默写代码。B 站当时的技术生态里推荐系统、内容审核、视频理解、弹幕分析这些方向都依赖算法工程师所以题目里出现不少机器学习相关知识点完全在预期内。可以这么说这套题测的是你的计算机基础是否扎实、机器学习理论是否成型、遇到未知问题时有没有分析框架这三条线互相交织构成了整份卷子的骨架。1.2 从考点分布看B站需要什么样的人如果把第二套笔试题的考点拆开看通常可以分成三块第一块是数据结构与经典算法包括数组、链表、字符串、树、图、排序、查找、动态规划、贪心等。这一块占了基础分的大头也是最容易失分的地方因为题目往往要求手写完整实现不能只写思路。第二块是机器学习与深度学习基础包括聚类、KNN、回归、梯度下降、反向传播、过拟合、评价指标等。这类题对非科班同学来说可能有点压力但考察深度不会太夸张主要看核心概念是否清晰、能不能手工推导简单公式。第三块是数学与优化方法常见的有快速幂、粒子群算法、模拟退火、PID、卡尔曼滤波等。这些不一定每套卷子都会考但作为算法岗尤其是涉及音视频、推荐、自动控制类业务的岗位偶尔会作为扩展题出现。从考点分布也能反向看出 B 站对算法岗的期待既要基础扎实又要有一点业务嗅觉还要具备快速学习新算法的能力。这套题的目的不是淘汰人而是筛选出真正具备这些素质的候选者。2. 数据结构与基础算法笔试的稳分盘2.1 排序算法别以为只会冒泡就能过排序算法几乎是算法笔试的“开胃菜”但也是最容易被低估的题目。B 站这套题里如果有排序题大概率不会让你写冒泡排序那太没区分度了。更常见的做法是让你比较几种排序算法的复杂度或者手写快速排序、堆排序并分析在特定数据下的表现。先放一个标准的快速排序实现很多人能写出来但边界处理容易出问题void quickSort(vectorint nums, int left, int right) { if (left right) return; int i left, j right; int pivot nums[left (right - left) / 2]; while (i j) { while (nums[i] pivot) i; while (nums[j] pivot) j--; if (i j) { swap(nums[i], nums[j]); i; j--; } } quickSort(nums, left, j); quickSort(nums, i, right); }这里最容易踩的坑有三个一是递归结束条件不加等号导致无限递归二是取锚点直接取 nums[left]在数组已经升序时会退化成 O(n²)三是在 while 循环里交换后忘记移动指针造成死循环。堆排序同样容易出问题。建堆时要从最后一个非叶子节点开始向下调整而不是从根节点开始。很多同学写成从 0 到 n 调整结果堆根本不成形。笔试时建议在草稿纸上画一遍数组转堆的过程再动手写代码。另外快速排序不稳定堆排序不稳定归并排序稳定但不常手写这些结论都要能说出来。别小看这一分面试官问了“稳定排序有哪些、为什么不稳定”的时候答不上来很扣分。2.2 KMP的next数组纸上手算比写代码更重要热搜词里正好有一条“在 kmp 算法中对于模式串 pabacaba其 next 数组”。这几乎就是原题级别的考点。KMP 的核心其实不是匹配函数而是 next 数组的计算。很多同学会用模板但题目让你手动计算 next[i] 时一下子就露馅了。在 KMP 算法中通常有两种 next 数组定义。一种是 next[i] 表示模式串前 i 个字符组成的子串的最长相等前后缀长度另一种定义更常见于考试即 next[i] 为失配时模式串应回退到的下标位置此时 next[0] -1。我们按经典定义来算 p abacaba 的 next 数组。先把这个字符串拆开看子串 a长度为1没有相等前后缀next[0] -1对应位置0。子串 ab最长相等前后缀长度为0next[1] 0。子串 aba前缀 a 和后缀 a 相等长度为1next[2] 1。子串 abac前缀 a 和后缀 c 不相等next[3] 0。子串 abaca前缀 a 和后缀 a 相等长度1next[4] 1。子串 abacab前缀 ab 和后缀 ab 相等长度2next[5] 2。子串 abacaba前缀 aba 和后缀 aba 相等长度3next[6] 3。所以按这个定义next 数组是 [-1, 0, 0, 1, 0, 1, 2, 3]。注意这里算到了最后一个字符后所以数组长度是模式串长度加 1。手写 KMP 的完整代码也很考察功底void getNext(const string p, vectorint next) { int n p.size(); next.resize(n 1); next[0] -1; int j 0; int k -1; while (j n) { if (k -1 || p[j] p[k]) { j; k; next[j] k; } else { k next[k]; } } }这里有个优化版是当 p[j] p[k] 时直接跳 next[k]避免重复比较。笔试时如果时间紧张建议先写未优化版再把逻辑讲清楚。计算 next 数组的过程就是 KMP 的难点匹配过程反而是顺着思路往后推。2.3 图论题Dijkstra和二分图的常见考法图论在算法岗笔试里的出现频率不低尤其是推荐、社交网络分析、路径规划等业务都离不开图。B 站这套题如果出图论很可能是考 Dijkstra 求最短路或者二分图匹配。先说 Dijkstra。用优先队列最小堆实现的代码是标准答案核心思想是贪心每次从堆顶取出距离起点最近的未访问节点用它去松弛相邻节点。时间复杂度 O(E log V)。笔试时除了写出来还要能回答一个问题为什么 Dijkstra 不能处理负权边。因为它的贪心假设是“当前最近的距离已经确定”但如果存在负权边后面可能找到更短的路径这个假设就崩了。二分图最大匹配常用匈牙利算法或 HK 算法。热搜词里的“HK算法”指的就是 Hopcroft-Karp 算法它比匈牙利算法快时间复杂度 O(E√V)。笔试不一定会让你完整实现 HK但可能会给你一个二分图让你判断是否能增广、怎么找增广路。核心概念要掌握交替路、增广路、匹配边与非匹配边的交替序列增广路径起点和终点都是未匹配点。如果考到图论题建议先画图再写代码把图的存储方式邻接矩阵还是邻接表想清楚。很多同学直接用邻接矩阵复杂度高且浪费空间数据量大一点就超时这属于笔试中的“隐藏失分点”。2.4 贪心算法凭什么它是对的贪心算法在笔试里几乎每年都出现但它不像动态规划那样有固定套路关键在于能否证明贪心选择的正确性。比如经典的活动选择问题按结束时间排序后依次选择这就是贪心跳跃游戏也是贪心记录当前能覆盖的最远位置。有一个高频考点是“区间调度”题目可能会问给定多个区间最多能选择多少个互不重叠的区间。贪心策略是按区间右端点排序然后依次取不重叠的区间。但面试官往往追问为什么按右端点排序而不是左端点因为右端点小留给后面的空间更大这是直觉上的理由。更抽象一点的贪心题比如哈夫曼编码、最小生成树的 Kruskal 算法本质上都依赖排序加贪心选择。复习时别只背结论要能举例子说明“如果替换掉某个选择结果会更差”这就是贪心证明的交换论证法。B 站的题不会考特别偏的贪心但一定会给你一个看起来像动态规划的题让你发现它其实能贪心求解这就要靠平常积累的题感了。3. 机器学习与深度学习考点算法岗的真正分水岭3.1 聚类和KNN基础模型也要能讲透机器学习部分总有几道题在“摸底”。聚类算法是重点尤其是 K-means。K-means 的步骤其实很简单随机选 K 个中心计算每个样本到中心的距离分配到最近的中心然后重新计算中心重复直到收敛。但考试不会只让你背步骤它可能会问K 值怎么选可以用肘部法则观察 SSE 下降的拐点也可以用轮廓系数评价聚类效果。还会问K-means 有哪些缺点比如对初始中心敏感容易陷入局部最优对噪声和离群点敏感。你如果能说出用 K-means 做初始化来缓解这些问题就是一个加分项。KNN 也是基础中的基础。热搜里有“knn算法的应用能力包括哪三个方面”我个人的理解是分类、回归和缺失值填充。分类和回归是常规用途缺失值填充则是利用相近样本的特征来估计缺失项。考场上如果遇到“KNN 的 K 值越大模型越容易欠拟合还是过拟合”这种题答案是 K 越小越容易过拟合因为决策边界更复杂对单个样本更敏感。聚类和 KNN 这类模型看起来简单但面试官很爱问细节比如距离度量选欧式距离还是余弦相似度特征要不要标准化。因为 KNN 是基于距离的算法如果特征量纲不统一大的特征会吞掉小的特征。这个细节能体现你有没有真正用过这些模型。3.2 训练过程与反向传播必考的“推导题”深度学习部分哪怕不手推完整的反向传播至少也要知道链式法则的核心逻辑。很多同学把反向传播理解成“梯度从输出层往前传”这个说法没错但要能写出具体公式。以一个最简单的两层神经网络为例损失函数是均方误差激活函数用 sigmoid。假设输入是 x第一层权重是 W1激活后得到隐藏层 h第二层权重是 W2输出是 y损失 L 0.5 * (y - target)^2。反向传播时先算输出层的梯度L/?W2再算隐藏层的梯度也就是把误差通过 W2 传回去。笔试中常见的是填空题或手工推导题比如给一个特定权重让你计算第一次迭代后的参数更新值。这时候要注意学习率、sigmoid 求导公式、链式法则的顺序。sigmoid 的导数有简便公式σ(z) σ(z)(1 - σ(z))这能省不少计算时间。另外要掌握常见损失函数和激活函数的搭配二分类用 sigmoid 交叉熵多分类用 softmax 交叉熵回归用 MSE。为什么分类不用 MSE因为 MSE 配合 sigmoid 容易导致梯度消失交叉熵在分类问题上收敛更快。这些“为什么”就是面试官区分候选人层次的常规问题。3.3 过拟合与模型评估经常被追问的细节模型评估这一块最容易考的是精确率、召回率、F1、ROC、AUC。别以为只有算法研究员才需要懂实际上任何算法岗都绕不开。笔试可能会给你一个混淆矩阵让你算精确率和召回率。也有可能会问正负样本不平衡时用准确率合不合适显然不合适应该更关注召回率、F1 或 AUC。过拟合的应对方法也要能张口就来增加数据量、正则化L1/L2、Dropout、早停、数据增强、简化模型结构。这里有个容易被忽略的点L1 正则化会让参数稀疏L2 正则化会惩罚参数平方和不会让参数变成零但会趋向零。所以 L1 可以做特征选择L2 更适合防止过拟合。笔试中常有选择题或者判断题比如“Dropout 在训练和测试时的行为有何不同”。训练时会随机丢弃一部分神经元测试时不会丢弃但需要对权重乘以保留概率保证输出分布一致。你要是没亲手搭过模型这种题很容易答错。4. 优化算法与数学基础拉开差距的扩展题4.1 从粒子群到模拟退火手推迭代公式B 站这套题的扩展部分可能会涉及一些经典优化算法正好热搜词里也有“粒子群算法原理”和“模拟退火算法”。粒子群算法PSO模拟鸟群觅食行为每个粒子有位置和速度两个属性。每次迭代时粒子会根据自身历史最优位置 pbest 和全局最优位置 gbest 调整速度v_i^{t1} w * v_i^t c1 * r1 * (pbest_i - x_i^t) c2 * r2 * (gbest - x_i^t)x_i^{t1} x_i^t v_i^{t1}其中 w 是惯性权重c1 是认知系数c2 是社会系数r1、r2 是 [0,1] 的随机数。如果在考场上碰到让你解释 PSO 的题一定要把每个参数的含义说清楚特别要强调 r1、r2 的随机性带来的探索能力。模拟退火算法则是模拟固体退火过程温度高时系统可以接受较差的解从而跳出局部最优温度逐渐降低接受劣解的概率也越来越小。核心公式是 Metropolis 准则若新解更优则接受若新解更差以概率 exp(-(ΔE)/T) 接受其中 ΔE 是能量差T 是当前温度。笔试时经常给一组参数让你判断在当前温度下是否接受某个较差解。你要会代入公式算概率然后与随机数比较。这类题难度不大但如果你没复习过现场推公式容易慌。4.2 从PID到卡尔曼滤波控制类岗位的加分项如果你投的岗位和视频播放、音视频同步、流量控制有关PID 控制算法也算是一个潜在的考点。PID 是比例、积分、微分三个环节的线性组合u(t) Kp * e(t) Ki * ∫e(t) dt Kd * de(t)/dtKp 是比例系数可以快速响应误差Ki 是积分系数消除稳态误差Kd 是微分系数抑制超调。让一个算法岗候选人解释 PID通常不是考你怎么调参而是看你能不能把控制思想用工程语言表达出来。结合业务的话可以类比视频播放过程中的码率自适应当前码率与目标码率的误差就是 e(t)比例项对应立即调整积分项对应长期偏差累计的修正微分项对应码率变化的趋势。卡尔曼滤波则是状态估计问题的经典方法。它假设系统状态满足线性高斯模型分两步走预测和更新。预测阶段利用状态转移矩阵和上一时刻的状态估计当前先验状态同时计算协方差矩阵更新阶段用当前观测值去修正先验估计输出后验状态。笔试如果考卡尔曼滤波大概率只考概念和公式形式不会让你手推完整推导。但你需要知道噪声协方差矩阵、观测矩阵这些符号的含义知道卡尔曼增益是用来平衡预测和观测的权重的。能把这个平衡的含义讲清楚基本就过关了。4.3 快速幂的边界与模运算快速幂是面试中超高频的“小硬核”知识点。尤其是处理大数运算时直接循环乘会超时或溢出快速幂能把 O(n) 降到 O(log n)。一个简单的递归写法long long fastPow(long long a, long long b, long long mod) { long long res 1; while (b 0) { if (b 1) { res res * a % mod; } a a * a % mod; b 1; } return res; }这里有几个特别容易踩的坑一是底数 a 很大时乘法可能先溢出再取模所以中间运算要多用 long long二是模数 mod 为 1 时答案恒为 0但有些同学会漏掉三是 b 为 0 时返回 1前提是 a 不为 0。如果笔试考快速幂不会只让写实现可能会结合组合数取模、斐波那契数列矩阵快速幂一起考。你要能看出它背后的二进制拆分思想把指数看作二进制每一位对应要不要乘上当前 a 的幂次。熟练掌握快速幂等于拿到一道必得分的题。5. 考场避坑那些让人“代码思路对但就是AC不了”的问题5.1 边界条件和空值永远是第一优先级笔试和面试不一样面试官可以看你的思路但笔试很多时候只认 AC 结果。代码写出来跑不过再好的思路也拿不到分。我复盘过很多人的笔试卷发现大部分失败案例都栽在边界条件上。比如求数组中的最大值时数组为空怎么办排序算法里数组长度为 0 或 1 怎么办字符串匹配时模式串为空是合法输入吗这些情况在 OJ 里都会有专门用例你只有加上完整判断才能过。一个习惯是写完函数第一步先填上“if (输入为空) return 默认值;”再考虑主逻辑。不要觉得这是多余笔试考的就是健壮性。另外二分查找的循环条件 while (left right) 是经典易错点少写一个等号就会死循环或者漏情况。5.2 时间复杂度与空间复杂度的权衡笔试不是只要通过还要考虑效率。有些题目直接给了数据范围比如 n 10^5说明 O(n²) 大概率会超时你需要想 O(n log n) 或 O(n) 的解法。如果你对复杂度不敏感可能会写出一个看起来很对但跑不完的程序。这里教大家一个快速判断方法1 秒大约能执行 10^7 到 10^8 次基础操作。如果 n 是 10^5O(n²) 就是 10^10 次肯定超时O(n log n) 是大约 1.7*10^6 次很安全。有时为了降低时间复杂度需要引入额外空间比如用哈希表把查找从 O(n) 降到 O(1)。笔试时不要怕空间除非题目明确说内存紧张否则用空间换时间是值得的。但在面试讲解时要主动说出“这个方案的空间复杂度是 O(n)如果想要优化到 O(1)可以……”这种话体现你的权衡能力。5.3 做题顺序和时间分配考试时最怕在一道题上死磕。一般整套笔试的时间在 120 分钟左右题目可能包括选择题、编程题、问答题。我的建议是先花 5 分钟通读全部题目把会做的题标记出来然后按“拿分性价比”排序。优先做你最熟悉、最容易 AC 的题保证基础分再做中等难度的题最后留时间思考压轴题。如果压轴题想了 15 分钟没有明确思路果断放弃回去检查前面写的代码把边界条件补上。从结果倒推一个粗心导致的全错比你空着一道压轴题更可惜。另外笔试环境通常不会提示缩进、括号匹配是否正确平时刷题尽量别依赖 IDE 的自动补全。手写代码时注意变量名清晰、函数结构完整万一有面试官查看你的代码这种规范性能留下好印象。6. 针对B站算法岗的备考路线6.1 刷题怎么刷才有效很多人都问刷题到底要刷多少道才够我的建议是“质量大于数量”。与其盲目刷 500 道简单题不如把 100 道高频题吃透。B 站算法岗笔试的侧重点是数据结构、排序、字符串、图论、动态规划和贪心你在 LeetCode 上按这几个 tag 刷就行。每个 tag 里挑出高频题然后按照“独立思考 - 看题解 - 自己重写 - 分析复杂度 - 找相似题巩固”的流程来。特别要注意的是手写实现不要只是在 IDE 里跑通要能在白板上或者拿个记事本写出无辅助的完整代码。考试时没有编译器和调试器一切靠脑内跑平常就要训练这种能力。我把刷题分为三轮第一轮按专题刷搞清楚每个数据结构和算法的使用场景第二轮随机刷模拟综合考试场景第三轮限时刷每道题控制在 30 分钟内训练做题节奏。这样三轮下来笔试时心里会比较有底。6.2 把算法原理和项目经验串起来算法笔试考的不只是代码还有你“能不能把理论和实践结合”。回答面试官时别把算法和项目割裂开讲。比如你在项目里做过视频推荐那就要能说清楚相似用户召回用的是 KNN 还是协同过滤排序用的是 GBDT 还是深度模型特征归一化有没有做冷启动怎么解决把项目里实际用到的模型和算法对照笔试知识点复习一遍会有奇效。比如你用过 K-means 做用户分群那就要能回答 K-means 的原理、K 值选择、收敛条件、缺点和改进。这样只要项目是自己的知识点就特别容易记住。另外B 站业务里弹幕情感分析、视频指纹、内容审核这类方向都可能成为面试追问的场景。建议考前了解一下推荐系统、NLP、CV 的基本概念哪怕没有实际项目也能在回答问题时显得知识面更广。6.3 考前模拟严格按笔试环境来最后一个建议特别实用考前至少完整模拟一次笔试环境。找一套难度接近的真题关闭所有浏览器标签用记事本或者白板写代码给自己掐时间。模拟的时候把自己当成正在笔试不能查资料不能翻笔记不能因为“想不起来”就跳过。模拟完以后一定要复盘。把每道题的耗时、卡壳点、边界错误都记录下来。你会发现很多问题在第一次模拟时暴露出来比如某类题总超时、某个排序模板不熟、看到图论题就紧张。然后用剩余的备考时间针对性地解决。我当时就是这样做的效果比单纯刷题好很多。尤其是手写 KMP 和快速排序模拟几次之后基本就是肌肉记忆了笔试时看到类似的题完全不慌。等到真正上考场状态会和技术面试一样稳定发挥就已经赢了一半。我在实际做这套题复盘时最大的体会是算法岗笔试更像是一场“基本功体检”你不需要所有题型都满分但一定不能让基础分白白丢掉。与其纠结偏题怪题不如把自己的解题模板打磨干净。最后再分享一个小技巧平时刷题时尽量用不同的方法解同一道题做完后自己给自己讲一遍思路这个过程练多了到了考场上你的表达和排查都会自然顺很多。
返回列表