B站算法校招笔试卷B全面复盘:考点解析与AC攻略

发布时间:2026/8/31 5:46:10
B站算法校招笔试卷B全面复盘:考点解析与AC攻略 B站2023校招算法方向笔试卷B我在牛客和几个技术群里看到不少同学在讨论这套题考完出来有人直呼选择题靠蒙、编程题靠暴力也有人觉得难度中规中矩。我把这套卷子的考点、题干风格和编程题思路完整复盘了一遍结合我过去几年带校招候选人、自己也参加过多场大厂笔试的经验写一份能直接参考的拆解。这篇内容主要面向正在准备算法岗校招的同学尤其是目标放在视频社区、推荐搜索这类业务方向的朋友。看完你至少能知道这套卷子到底在考什么、哪些知识点高频出现、编程大题用什么套路去拆解、以及平时刷题要注意哪些容易翻车的地方。先说结论这份卷子不是单纯考八股文而是把数据结构与算法基础 机器学习 / 深度学习理论基础 代码落地能力三件事放在一张卷子里一起验货。选择题覆盖面很广从排序算法到图论、从KMP到聚类什么都有编程题则是典型的你不光要懂原理还要能撸代码并且要考虑复杂度和边界条件的风格。下面我按题型、考点、实战拆解和避坑四大部分展开。1. 试卷整体结构与考察思路拆解1.1 题型分布与分值逻辑先别急着背题把游戏规则看清楚比什么都重要。从2023校招算法方向笔试卷B的情况来看B站这套笔试大体延续了互联网大厂算法岗笔试常用的组合方式单选题 / 多选题 编程题部分场次还会夹带一两道简答或填空题。我根据多个参与者的复盘信息整理了一份参考结构题型大致题量参考分值考察侧重单选题15~20题每题2~3分数据结构、算法复杂度、机器学习基础、深度学习基础多选题5~8题每题3~4分容易丢分考察概念边界和细节辨析编程题2~3题每题20~30分手写代码能力算法设计、复杂度控制、边界处理简答 / 填空题0~2题10分左右某些方向会考察模型推导或基础公式这个分值结构有两层含义。第一选择题决定了你能不能进入面试编程题决定了你能不能高分进入面试。很多人笔试挂就挂在选择题上因为编程题只要暴力解能过部分用例就有分但选择题错一半以上基本就没戏了。第二多选题的比重比想象中大它不是在问你哪个对而是在问哪些对这需要你真正理解概念的边界而不是背一个模糊的印象。另外值得注意的是B站算法岗笔试不像有些公司那样分成研发卷和算法卷它就是一个大杂烩。这意味着你不光要会排序、会图论还得知道SVM的核函数、XGBoost的增益计算、KL散度的含义这些机器学习内容对CV / NLP方向的同学反而可能要额外补一下基础数据结构。1.2 B卷与A卷的差异化侧重既然有卷B那大概率还有卷A。从多位考生的反馈来看两套卷子整体难度相当但侧重点有差异。A卷更偏通用算法比如排序、链表、二叉树这些经典题目占比更高机器学习部分相对简单更多是概念性记忆。而B卷则明显加强了对推荐 / 搜索业务相关的算法考察比如KNN的应用、聚类算法、BM25这类信息检索概念在选择题里的出现频率更高编程题里也出现了更贴近流数据处理场景的TopK问题。这说明一个信号B卷可能更贴近B站主站的推荐、搜索、用户增长这类业务方向。如果你是投递这些岗位刷题时就要格外注意海量数据场景下的算法设计而不是死磕竞赛级别的偏题怪题。我个人的建议是无论拿到A卷还是B卷准备的核心都应该是数据结构的经典操作 机器学习的经典模型 两个能完整写出来的算法模板比如堆排和Dijkstra。这三样东西稳了这套卷子就能拿个不错的分数。2. 核心考点详解数据结构与算法基础2.1 KMP 算法与 next 数组字符串题的分水岭今年的热词里在 kmp 算法中对于模式串 pabacaba其 next 数组这个话题被反复搜显然这道题在试卷上坑了不少人。字符串匹配算法里KMP 几乎是笔试必考而KMP的难点不在于匹配过程本身在于next数组的推导。先明确一个定义next[i] 通常表示模式串前 i 个字符组成的子串中最长相等前后缀的长度。注意这里有两个版本的定义有的教材把next[i]定义为最长相等前后缀长度有的定义为最长相等前后缀长度再减1有的叫失配函数笔试时一定要先看题目给的公式否则答案会差一个1。以模式串 p abacaba 为例我完整推一遍 next 数组next[0] 0长度为1的前缀 a没有真前后缀所以为0。next[1]子串 ab最长相等前后缀为0。next[2]子串 aba前缀 a 和后缀 a 相等最长长度为1。next[3]子串 abac前缀 a 后缀 c不相等前缀 ab 后缀 ac不相等所以为0。next[4]子串 abaca前缀 a 后缀 a 相等长度为1前缀 ab 后缀 ca 不等前缀 aba 后缀 aca 不等所以最长长度为1。next[5]子串 abacab前缀 ab 和后缀 ab 相等长度为2检查更长的没有所以为2。next[6]子串 abacaba前缀 aba 和后缀 aba 相等长度为3所以为3。所以最终 next 数组是 [0, 0, 1, 0, 1, 2, 3]按最长相等前后缀长度的定义。如果题目定义成失配时跳转的位置那数组会整体偏移一般是用 [0, 0, 1, 0, 1, 2, 3] 这个值再根据实现做调整。手算不是难点真正的坑在于代码实现时next数组的递推经常写错。这里给一个标准的构建模板def build_next(p): m len(p) nxt [0] * m j 0 for i in range(1, m): while j 0 and p[i] ! p[j]: j nxt[j - 1] if p[i] p[j]: j 1 nxt[i] j return nxt笔试中如果给你一个模式串让你求next数组最快的方法是手画前缀后缀一个一个比对千万别凭感觉直接写。我见过太多同学把 abacaba 的 next 数组写成 [0, 0, 1, 0, 2, 1, 3]这就是对前后缀必须是真前后缀这个条件没吃透next[4] 的子串是 abaca它不存在长度为2的相等前后缀因为前缀ab和后缀ca对不上。2.2 排序算法底层原理与变式应用排序算法在这套卷子里几乎是以题题都有的方式出现的。比如冒泡排序C实现、堆排序算法、快速排序、归并排序每个都可能成为选择题或编程题的引子。别以为排序只会考时间复杂度是多少这种送分题B卷里很多题目是把排序当成工具考你基于排序的变形问题。先看基础对比排序算法平均时间复杂度最坏时间复杂度空间复杂度稳定性冒泡排序O(n^2)O(n^2)O(1)稳定快速排序O(n log n)O(n^2)O(log n)不稳定归并排序O(n log n)O(n log n)O(n)稳定堆排序O(n log n)O(n log n)O(1)不稳定选择题最容易挖的坑是堆排序空间复杂度。很多人以为O(1)但如果你用递归建堆函数栈空间也可能被算进去更常见的是把堆排序误认为稳定排序实际上堆排序在调整过程中会改变相同元素的相对顺序它不稳定。B卷编程题里高频出现的是TopK和第K大问题。解决思路有这么几种全排序取前K个时间复杂度 O(n log n)适合K很大的情况。堆方案维护一个大小为K的最小堆遍历一遍每次和堆顶比较时间复杂度 O(n log K)。这个方案在K远小于n时非常快。快速选择算法基于快速排序的partition思想平均时间复杂度O(n)但最坏会退化到O(n^2)。如果数据规模大到无法全部读入内存就得用外部排序 堆的配合。笔试时优先推荐堆方案因为代码短、复杂度稳定、不容易被极端数据卡掉。下面这个模板可以直接默写import heapq def top_k(nums, k): heap [] for num in nums: if len(heap) k: heapq.heappush(heap, num) elif num heap[0]: heapq.heapreplace(heap, num) return heap2.3 图论与贪心Dijkstra、拓扑排序、二分图图论相关的热词这次出现了不少比如dijkstra算法、kahn算法、二分图hk算法、快速幂算法c等。这说明B卷在选择和编程题里图论的占比不低。先说说Dijkstra。它解决的是单源非负权最短路问题。核心思想是贪心每次从未确定的节点中选一个距离起点最近的节点松弛它的所有邻边。为什么Dijkstra的贪心是对的因为在非负权图中当前距离起点最近的未确定节点不可能再通过其他路径变得更短因为绕路只会增加距离。一旦理解了这一点你就能记住Dijkstra不能处理负权边如果出现负权边要用Bellman-Ford或SPFA。笔试里Dijkstra的常见考法有两种。一种是选择题问你算法复杂度或适用条件优先队列实现的复杂度是 O((VE) log V)。另一种是编程题比如给定一个无向图求从节点1到节点n的最短路径长度这类题直接用堆优化Dijkstra模板就能过。模板核心如下import heapq def dijkstra(graph, start, n): dist [float(inf)] * (n 1) dist[start] 0 pq [(0, start)] while pq: d, u heapq.heappop(pq) if d dist[u]: continue for v, w in graph[u]: if dist[u] w dist[v]: dist[v] dist[u] w heapq.heappush(pq, (dist[v], v)) return dist再说拓扑排序热词里提到的kahn算法就是解决拓扑排序的经典算法。它的思路非常朴素不断找入度为0的节点把它加入结果序列然后删除它和它的出边重复这个过程。如果最后结果序列的长度不等于节点数说明图里有环。如果B卷编程题出一道课程表问题判断有向图是否能拓扑排序你直接用Kahn算法就好。这里有一个容易忽略的细节如果题目要求输出字典序最小的拓扑序你得把入度为0的节点放进优先队列而不是普通队列每次取字典序最小的那个。二分图相关的内容在热词里也出现了。二分图判定一般用染色法二分图最大匹配优先用匈牙利算法如果图特别大就用HK算法。B站这套卷子对二分图的考察大概率停留在选择题比如下列哪个问题可以转化为二分图最大匹配你需要记住几个经典转化任务分配、棋盘覆盖、最小点覆盖 最大匹配数Kőnig定理。3. 机器学习与深度学习算法考点解析3.1 经典机器学习算法KNN、KMeans、XGBoost、卡尔曼滤波B站的算法卷机器学习部分不深但范围广。热词里knn算法的应用能力包括哪三个方面、聚类算法、xgboot算法、卡尔曼滤波算法这些词被反复搜说明它们确实是考点。KNN也就是K近邻算法是惰性学习的代表。它没有显式的训练过程而是在预测时计算样本到所有训练样本的距离取最近的K个邻居投票决定类别。KNN的三要素是距离度量、K值选择、分类决策规则。热词里问应用能力包括哪三个方面我猜答案大概率是指它的应用能力可以概括为分类、回归和密度估计。不过我也看到过另一种问法是问KNN的三个基本要素所以考场上一定要先看题目问的是哪三个。KMeans是聚类算法里面最常考的。它的流程就是四步随机选K个中心把每个样本分到最近的中心重新计算每个簇的中心重复直到中心不再变化。选择题通常考K值怎么选常见的是肘部法则和轮廓系数。有一个细节很容易忽略KMeans对初始中心敏感不同的初始化可能导致不同的聚类结果所以很多工程实现会用KMeans来做初始化。XGBoost在热词里也出现了这是GBDT类模型的代表。笔试不太会让你手推XGBoost的完整二阶泰勒展开但你要知道它和普通GBDT的区别在于目标函数引入了二阶导数信息并且加了正则项来控制模型复杂度。选择题如果问XGBoost相比GBDT的主要改进答案基本就往这两个方向靠。卡尔曼滤波是信号处理和控制论里的经典算法热词里也占了一个位置。它的核心是预测 更新两步走先用状态转移方程做先验预测再用观测值做后验修正。B站有视频播放、音视频相关的业务所以卡尔曼滤波偶尔会出现在选择题里考察基本思想不考推导。3.2 损失函数、KL 散度与 ELBO理论基础不能只背公式热词里专门出现了一条kl elbo 算法原理详解这说明B卷对概率图模型和变分推断是有涉猎的。KL散度用来衡量两个概率分布之间的差异。公式是KL(P || Q) Σ P(x) · log(P(x) / Q(x))注意KL散度不是距离因为它是非对称的KL(P||Q) 不等于 KL(Q||P)。这个不对称性是一个经典考点。交叉熵和KL散度的关系也要知道交叉熵 信息熵 KL散度在分类问题里我们最小化交叉熵其实等价于最小化模型分布和目标分布之间的KL散度。ELBO在变分自编码器VAE里是核心概念。它的全称是Evidence Lower Bound证据下界。推导的核心思路是log P(x) ELBO KL(q(z|x) || p(z|x))因为KL散度大于等于0所以 log P(x) ELBO。直接最大化 log P(x) 需要计算后验 p(z|x)这通常是不可解的所以我们转而最大化ELBO。对于VAEELBO可以拆成两项重构误差项 正则项近似后验和先验之间的KL散度。如果考场上遇到这类题不要慌记住一句话KL散度非负且不对称ELBO是log似然的下界VAE的损失函数就是负ELBO。这三句背出来至少能拿一半分。3.3 强化学习与启发式优化模拟退火、粒子群为什么也出现在试卷里热词里出现了模拟退火算法和粒子群算法原理这类启发式优化算法在B站算法卷里的定位很有意思它们不会作为编程大题出现但会在选择题里作为优化算法来考察你是否具备足够宽的算法视野。模拟退火的核心思想来自物理退火过程系统温度高时分子运动剧烈接受差解的概率大温度降低后接受差解的概率变小。在算法里我们用一个概率来判断是否接受一个新解即使它比当前解差。这个以一定概率接受差解的机制让算法有机会跳出局部最优最终收敛到全局最优附近。粒子群算法则是模仿鸟群觅食行为。每个粒子有位置和速度迭代时根据个体最优位置和全局最优位置更新速度再更新位置。选择题如果问你粒子群算法的核心更新公式涉及哪几个变量答案是当前位置、当前速度、个体历史最优、全局历史最优。我个人的判断是这类题目属于区分度题一个认真复习过的人不会丢分一个只刷LeetCode的人肯定丢分。所以备考时不要觉得这些不是机器学习不看了恰恰是这些偏门知识点决定了你能否从人群里跳出来。4. 编程大题实战拆解从读题到 AC 的完整思路4.1 经典题TopK / 第 K 大优先队列一写一个准B卷编程题大概率有一道海量数据求TopK的变体。比如给定一个长度为N的数组求第K大的元素或者从数据流中随时查询第K大的数。这类题最稳的思路是堆。但使用堆之前一定要先确认数据规模如果N在10^5级别直接用快速选择或排序都能过。如果N在10^7级别就不能全排序要用大小为K的堆。如果是数据流场景除了堆之外还要考虑动态更新。一个常见坑是求第K大用最小堆还是最大堆。很多同学容易搞混。记住求第K大维护一个大小为K的最小堆堆顶就是答案。因为堆里保留的是最大的K个数其中最小的那个就是第K大。反过来求第K小维护一个大小为K的最大堆堆顶就是第K小。如果你笔试时间紧张暴力解法也能拿分。先把数组从大到小排序输出第K-1个元素时间复杂度 O(n log n)。在数据量不大的情况下这种解法至少能过掉一部分用例千万不要什么都不写。4.2 经典题最短路问题Dijkstra 邻接表是默认搭配编程大题第二道经常是图论题。B站的场景是视频推荐和关系网络出用户关注关系图求最短路径这种题完全不意外。题目大概长这样有N个用户和M条关注关系每条关系有一个权值求从用户1到用户N的最短路径。这就是标准的最短路模板题直接用前面给的Dijkstra模板就能AC。但有几个细节会决定你能不能拿满分第一图规模。N可能在10^5级别绝对不能用邻接矩阵O(N^2)会爆内存和时间必须用邻接表。Python里通常用字典存graph[u] [(v, w), ...]。第二节点编号是从0开始还是从1开始这直接影响数组大小用错就会索引越界。第三路径可能不存在。题目如果没有保证图连通你要能输出-1或题目指定的值。如果题目约束条件说到有权值为负的边那就不能再用Dijkstra要改用Bellman-Ford或SPFA。判断依据很简单看到权值非负用Dijkstra看到可能有负权用Bellman-Ford要求任意两点最短路用Floydn500时。4.3 经典题动态规划与记忆化搜索识别最优子结构是关键编程题最后一道如果不出图论大概率出动态规划。热词里贪心算法、算法流程图这类关键词也说明DP 贪心的组合考察是B站笔试的一个定番。动态规划的难点不是写状态转移方程而是如何快速识别这题能用DP。判断标准就两个有没有最优子结构有没有重叠子问题。举几个经典的例子背包问题选或不选取最大价值。最长公共子序列LCS两个序列结尾字符是否相等。编辑距离插入、删除、替换三种操作取最小代价。打家劫舍相邻不能选取最大和。如果实在不知道怎么优化成一维DP先从二维暴力开始写。比如编辑距离dp[i][j]表示s1前i个字符和s2前j个字符的最小编辑距离转移方程是if s1[i-1] s2[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写出这个时间复杂度O(nm)空间复杂度O(nm)如果题目给的数据范围是1000以内能直接AC。如果给的是10^5级别再用滚动数组优化空间。实战经验告诉我真正决定能不能AC的关键往往不是算法本身而是初始化是否正确。dp[0][j]和dp[i][0]的边界必须在循环之前填好这一步漏了后面全是错的。5. 备考复盘与避坑指南5.1 笔试踩坑实录哪些地方最容易被扣分我把这套卷子的典型失分点整理成了一张表这些是我在群里看大家吐槽以及带人复盘时总结出来的高频问题失分点具体表现规避方法边界条件漏判数组越界、空输入、单元素输入每道编程题先写三个测试用例空、最小、正常时间复杂度超限暴力解法在数据量大时TLE先估算数据范围10^5以上就要考虑O(n log n)数值溢出int存不下大数结果用int输出涉及累加或乘法优先用long long / Python int题目定义没看清next数组的定义、K是第大还是第小读题两遍画出关键条件再动手多选题漏选概念边界模糊导致犹豫平时用排除法找反例练习输入输出格式错误多输出空格、少换行、string读成int牛客上多做本地模拟别只在LeetCode刷有一条我想单独强调一下B站笔试用的是牛客网系统输入输出格式和LeetCode完全不同。很多同学在LeetCode上写函数写习惯了一到牛客的ACM模式就懵了连while True: try: ... except: break这种循环读入都忘了。备考时一定要去牛客上找几套真题练手把input()和sys.stdin.readline()用熟。5.2 刷题优先级与时间分配如果你从现在开始准备我给一个三梯队的刷题优先级这是针对B站这套笔试卷风格定制的第一梯队必拿分数组与字符串操作、哈希表、排序算法手写、二分查找、链表增删改查、栈和队列。这些题目占卷面40%左右必须练到条件反射。第二梯队拉开差距二叉树遍历与序列化、堆的应用TopK、合并K个有序链表、图论Dijkstra、拓扑排序、并查集、动态规划背包、LCS、编辑距离、贪心区间问题。这些题目占卷面40%是编程题的主要来源。第三梯队锦上添花KMP、字符串哈希、树状数组与线段树、状态压缩DP、二分图匹配、启发式算法概念。这些题目占比不大但选择题里出现了就是区分度建议以理解原理为主不需要刷大量题目。时间分配上如果距离笔试还有一个月第一周专攻第一梯队的模板题第二周开始做第二梯队的专项训练第三周做整套模拟卷重点感受牛客的输入输出模式最后一周查漏补缺把错题和模板复习一遍。不要一上来就刷LeetCode hard题性价比太低。5.3 应试策略与心态管理最后说一点应试层面的东西这部分是我看太多人吃亏后最想讲的。第一先做编程题再做选择题。编程题分值高、区分度大而且在考试刚开始头脑最清醒的时候更容易AC。选择题即使只剩20分钟靠直觉和排除法也能蒙对一部分但编程题如果只剩20分钟基本就只能写个暴力解。第二编程题先想暴力再想优化。最怕的不是你AC不了而是你笔试题提交了但没编译通过。先写一个能跑出正确结果的暴力解再慢慢优化。在牛客系统里暴力解通常能过30%~60%的测试用例这部分分先拿到手再说。第三选择题不确定的选项用找反例的方法解决。比如选项说堆排序是稳定的你就想堆排序在调整堆的时候相同元素会不会交换位置会所以不稳定。这个思考过程比死记硬背要可靠得多。我个人的体会是B站这套笔试卷B并不是要故意刁难你它更像是一次全面的体检看看你作为一个算法工程师候选人基础功底扎不扎实、代码落地能力的下限在哪里。如果你能把经典的排序、KMP、Dijkstra模板写到默写的程度把机器学习的经典模型讲清楚再加上一点应试技巧通过笔试的把握会大很多。最后再分享一个小技巧考前花半小时把数组、字符串、二叉树、图论、DP这五类的模板代码手写一遍不要看参考答案纯粹凭记忆写。写不出来的地方就是你的薄弱点重点补。这个习惯我每次面试之前都会做实测下来比刷十道新题管用得多。