1. 卷B的整体画像:题型、时间和考察重点
2023届校招季,B站算法方向的笔试试卷分成了A、B两个版本。很多同学看到卷B第一反应是"B卷是不是比A卷难",或者反过来觉得"B卷是备胎卷"。我在实际刷题和复盘中发现,分卷的逻辑没那么玄乎,更多是为了防止题目泄露和同场考试作弊,难度系数并不存在明显倾斜。真正拉开差距的,是卷子里埋的那些"看着面熟、一做就错"的细节。
从题型结构来看,卷B大致分为三个部分:单选/多选题、简答题(部分批次有)和编程题。整体时长一般是120分钟,题量在30到35道选择题加3道编程题左右。选择题覆盖数据结构、算法设计、机器学习基础和少量深度学习概念;编程题则围绕经典算法展开,三道题通常对应"简单、中等、偏难"三个梯度。需要特别说明的是,不同批次、不同岗位(推荐算法、内容理解、NLP方向)的卷面可能略有差异,但核心考点高度集中在热搜词里那些高频算法上——KMP、堆排序、贪心、动态规划、二分图匹配等,全都是大厂笔试的常客。
这里建议准备阶段先明确投递岗位的方向。B站算法岗不只是推荐算法,还有视频理解、弹幕分析、搜索排序等方向。卷B的题目虽然不区分岗位,但你在复习时的重心应该结合岗位来调整。比如投视频理解方向,就可以多花点时间看CNN、图像特征提取相关的基础题;投推荐方向,就重点准备特征工程和排序损失相关的内容。笔试不是终点而是筛选起点,它的目标不是让你拿满分,而是在两小时内尽量稳定输出,把会做的题全做对。
1.1 卷A和卷B的分工逻辑
我见过不少同学在备考群里争论卷A难还是卷B难,实际上两个版本的题库是同一套核心考点库随机抽题的。B站的笔试系统会把题库里的题目按照难度、知识点打散,然后随机拼成A卷和B卷。也就是说,你可能在B卷遇到一道A卷同学没有遇到的KMP变形题,这完全取决于抽题运气,和卷号本身没有必然关系。
不过卷B有一个容易被忽略的特点:因为它是后生成的备用卷,部分题目的表述方式可能不像A卷那么"直白"。比如同样考贪心算法,A卷可能直接给一个区间调度问题让你选贪心策略,B卷可能会包装成一个视频推荐场景中的资源分配问题。这不是刻意刁难,而是题库里本来就是这么设计的。所以复习时不能光背结论,要看懂题目的本质模型,把场景化的描述翻译成算法问题。
1.2 笔试环境的那些隐性要求
笔试是线上进行的,这里有一个很多应届生会踩的坑:环境准备。B站用的在线笔试平台一般支持本地IDE调试后再粘贴代码,但前提是你提前把环境测好。摄像头监控、屏幕录制、浏览器切屏检测这些环节,每年都有人因为无意间切出浏览器被警告甚至取消成绩。我的建议是提前用一个闲置的浏览器专门跑笔试,关掉所有消息通知,把微信、钉钉、QQ全部退出登录。手机放到拿不到的位置,因为部分平台的防作弊规则要求手机处于监控视频范围内,但又不能使用。
另外要提醒的是,虽然平台支持多种语言提交,但在算法笔试中,Python和C++/Java的选择会直接影响你的做题速度。B站的判题系统对Python的时间限制通常比C++宽松一些,但并非常规保证。我习惯用Python打表找思路、用C++提交最终代码,但如果只擅长一门语言,就老老实实用熟练度最高的那门,不要在笔试现场尝试换语言。
2. 经典算法选择题:从KMP到堆排序的考点复盘
选择题部分是卷B拿分的基础盘,也是很多人口中"送分题"的重灾区。为什么说是重灾区?因为选择题考查的往往不是你会不会写代码,而是对算法细节的记忆和敏感度。一个算法你能写出正确代码,不等于你能清楚说出它失败时回溯几步、空间复杂度是O(1)还是O(n)、排序算法是否稳定。下面这些高频考点,是备考时反复出现的。
2.1 KMP算法与next数组的计算
热搜词里有一条非常具体的:"在KMP算法中,对于模式串p='abacaba',其next数组"。这个知识点几乎每场笔试都会出现,要么直接考next数组计算,要么考匹配过程中的移动次数。我在刷题群里看到不少同学栽在这里,原因是对next数组的定义没有统一。
这里先明确一件事:next[i]在不同教材里有两种定义,一种表示"前缀和后缀的最长公共长度",另一种表示"失配后跳转的位置"。B站笔试卷B里如果给出了"next[i]定义为..."的说明,就以题目说明为准;如果没给,就要从选项里反推它采用的是哪种定义。
以模式串p="abacaba"为例,计算前缀函数(PMT版本):
- next[0] = 0,单个字符没有真前缀和真后缀
- next[1] = 1,前缀"ab"的真前缀为"a",真后缀为"b",不匹配,最长公共真前后缀长度为0,注意此时长度为1的子串"a"不能算,因为真前缀/真后缀不能等于整个子串
- 但实际上很多教材对"ab"取next值是0
- next[2] = 1,前缀"aba"中,真前缀"a"等于真后缀"a"
- next[3] = 2,前缀"abac"中,"ab"等于"ac"吗?不,"a"等于"c"吗?不,所以是0?等等,这里要小心
我重新写一下。模式串"abacaba"的各个前缀:
- 前缀1: "a"
- 前缀2: "ab"
- 前缀3: "aba"
- 前缀4: "abac"
- 前缀5: "abaca"
- 前缀6: "abacab"
- 前缀7: "abacaba"
逐个求最长公共真前后缀长度(很多教材称为next数组,注意下标从0开始还是从1开始有差异):
- "a":0
- "ab":0
- "aba":1("a" = "a")
- "abac":0
- "abaca":1("a" = "a")
- "abacab":2("ab" = "ab")
- "abacaba":3("aba" = "aba")
所以按这种定义,next数组是[0,0,1,0,1,2,3]。如果题目要求下标从1开始且next[1]=0,则需要移位,得到[?,0,0,1,0,1,2,3]这样的形式。这就是为什么很多同学对答案发现差一位——不是算错了,是定义不同。
考试中的技巧是:先把候选答案里最可能的定义确定下来,再快速手算验证。手算时可以只算前三个和后三个,不需要全算,因为选择题往往可以通过排除法缩小范围。
2.2 排序算法的稳定性和复杂度辨析
排序算法在卷B里的出现率几乎百分之百,但考查方式比较固定:给一个具体场景,问选哪种排序最合适,或者给几个复杂度对错的判断。我在整理往年题目时发现,最容易混淆的是快排和堆排序的稳定性。
稳定性指的是相等元素的相对顺序在排序前后保持不变。快排是不稳定的(因为分区交换可能改变相对位置),归并排序是稳定的,堆排序是不稳定的,插入排序和冒泡排序是稳定的。很多同学只记住了"快排不稳定",但遇到"堆排序是否稳定"反而犹豫。这里给一个联想记忆法:凡是排序过程中元素会"跳来跳去"的,基本都不稳定,比如快排交换跨过了多个位置,堆排的堆调整会把最后元素换到堆顶。而插入、冒泡、归并都是相邻元素或局部区间的有序合并,相等元素的相对顺序不会被破坏。
复杂度方面,堆排序和归并排序在所有情况下的时间复杂度都是O(n log n),快排最坏是O(n²),但平均是O(n log n)。选择题如果问"最坏情况下时间复杂度最小的排序算法",那就是堆排序和归并排序二选一;如果问"额外空间复杂度为O(1)的稳定排序",经典答案是没有——因为归并需要O(n)额外空间,而堆排虽然O(1)空间但不稳定。这种题没有刁钻,纯粹考基本功。
2.3 贪心和动态规划的界定
卷B的选择题里经常出现"以下哪个问题适合用贪心算法解决"或者"动态规划的核心特征是什么"。这类题失分的原因不是概念不懂,而是选项里总有一个"看起来像贪心但实际需要动态规划"的干扰项。
判定贪心算法能不能用的方式是看贪心选择性质和最优子结构。说得直白一点:每一步做出当前看起来最好的选择,就能得到全局最优解,那就适合贪心;如果当前选择会影响后续选择,局部最优组合出不了全局最优,就要考虑动态规划。
一个常见的对比例子是硬币找零问题。如果硬币面额是1、5、11,要凑15元,贪心算法会先取11再取4个1,共5枚;但最优解是3个5,共3枚。这就是贪心失效的场景。换成面额体系是1、5、10、25的美元硬币,贪心选择又成立。所以选择题只要出现"硬币找零""背包""区间"这些关键词,先别急着选贪心,看清楚面额或限制条件再判断。
3. 编程题实战拆解:状态设计比AC更重要
编程题是卷B中最能拉开差距的部分,也是判卷时最看重代码质量的题目。三道题的时间分配如果失衡,很容易出现"第一题写太久、第三题没时间看"的局面。下面我按实际考试中遇到的题目类型拆解一下思路,重点不是背代码,而是建立"从读题到AC"的完整链路。
3.1 送分题的拿分姿势
第一道编程题通常是基础数据结构题,难度接近LeetCode简单题到中等题的过渡区间。常见类型包括字符串处理、数组操作、栈和队列的模拟。这道题的目标是稳拿全分,所以不要刻意炫技。
我印象比较深的一道题是模拟括号匹配扩展版:给定一个只包含()[]{}的字符串,判断是否有效。多数人会直接用栈,但题目会加一个限制——字符串长度最大是10^6,这就意味着递归写法或O(n²)的字符串替换法会超时。正确思路是顺序扫描,遇到左括号入栈,遇到右括号检查栈顶是否匹配。边界条件是字符串可能为空、可能只有左括号、可能右括号先出现。这些边界情况在笔试中比算法本身更容易扣分。
答题策略上,我建议先写一个最朴素的版本跑通样例,再考虑优化。即使最终版本不是最优解,也要保证在时间限制内能跑完题目给出的最大数据量。笔试平台会隐藏测试用例,如果只过了公开样例,得分依然很低,这是很多应届生容易忽略的细节。
3.2 动态规划题的完整推导
第二道编程题大概率是动态规划,因为它能有效考察状态定义、状态转移、初始化和边界处理四件事。我在卷B里遇到的动态规划题,题干通常不会直接说"这是一道动态规划题",而是包装成视频平台的资源调度场景,比如"在N天内有M个视频需要上线,每个视频有固定的制作周期和收益,求最大收益"。
解这类题的步骤我建议固定成四步走:
- 划分子问题:把"前i天能获得的最大收益"作为状态,而不是"第i天是否上线某个视频"
- 确定转移方程:状态
dp[i]可以由dp[i-1]和dp[i - duration[j]] + profit[j]转移而来 - 初始化:
dp[0]=0,所有位置先设为负无穷或0,看题目求最大值还是最小值 - 确定遍历顺序:如果状态依赖前一个维度,就正序;如果依赖更小下标,也要保证被依赖的状态已经计算完成
写代码时,要注意初始化不能随便给0。如果题目求最大值,且收益可能有负数,初始化为0会导致负收益状态被跳过,算出的结果偏大。这种细节选择题里也爱考,放在编程题里就是一个隐藏的WA点。
3.3 压轴题的策略性取舍
第三道编程题通常涉及图论、数论、二分答案或状态压缩,难度明显高于前两道。很多同学一看到第三题就开始慌,结果在第二题还没完全跑通的情况下去死磕压轴题,导致前两题也没拿满。
我的建议是:第三题先读题,把数据范围写在草稿纸上,快速判断自己有没有思路。如果前5分钟想不出来,立刻回去检查前两题的代码,尤其是边界和溢出问题。因为压轴题的通过率本来就低,拉开差距的地方在于前两题的正确率,而不是第三题能不能AC。
如果确实有思路,优先考虑暴力能否通过部分数据。笔试平台通常按测试点给分,暴力能过20%到40%的测试点,也比空着强。比如一道二分图匹配的题,数据量大时需要用HK算法,但数据量小的时候用匈牙利算法也能过一部分。热搜词里连续出现了"二分图HK算法""匈牙利算法",说明这个方向值得重点准备,但不要只会背代码,要明白HK算法是在匈牙利算法基础上用BFS找多条增广路来减少匹配趟数。
4. 机器学习与深度学习交叉考点不可忽视
B站算法岗的笔试卷B虽然以传统算法题为主,但机器学习相关考点占比不低,尤其是对推荐算法岗来说,这部分可能是决定是否进入面试的关键。选择题里容易出现"过拟合怎么解决""分类模型的评估指标有哪些""L1和L2正则化的区别"这类基础题,简答题偶尔会让手推一个逻辑回归的梯度更新。
4.1 分类指标和采样问题的坑
关于分类模型评估,卷B里高频出现的是准确率、精确率、召回率、F1值和ROC曲线的辨析。最容易错的是精确率和召回率的区别:精确率是预测为正类的样本中真正类的比例,召回率是实际正类中被正确找出的比例。推荐场景中,如果目标是尽量不漏掉用户可能喜欢的视频,就侧重召回率;如果目标是推送的头几条视频尽量精准,就侧重精确率。
另一个高频点是类别不平衡。题目可能会问:正负样本比例1:100时,用准确率评估模型有什么问题?答案是准确率会被多数类主导,哪怕全部预测为负类也有99%的准确率,看起来很高但毫无意义。这种题只要找准"准确率失效"这个关键点就行,不需要写公式。但如果你在简答题里能把采样方法(上采样、下采样)和评价指标选择(F1、AUC、PR曲线)写全,得分会明显高一些。
4.2 深度学习常见考点
深度学习在卷B中的考查更偏概念,不会让你在笔试现场搭建网络。常见的有:ReLU激活函数为什么比Sigmoid好、卷积层的参数量怎么算、Dropout的作用、为什么RNN容易梯度消失或爆炸。这些题目的答案相对固定,背熟基本不会失分。
卷积层参数量的计算方法是很典型的送分题:一个输入通道数为C_in、输出通道数为C_out、卷积核大小为K×K的卷积层,参数量是C_in×C_out×K×K,再加上偏置的话就是C_out个偏置项。比如输入3通道、输出64通道、3×3卷积,参数量就是3×64×3×3=1728,加上偏置64,总共1792。这种题不需要思考,只考验平时有没有留意公式。
Dropout的题也有固定套路:训练时按概率p随机丢弃神经元,推理时所有权重乘以(1-p)以保持输出期望不变。有的题目会反过来考,问你训练时如果没做inverted dropout,推理时应该怎么修正权重。只要记住"训练时缩放、推理时修正"的原则,就不会被绕进去。
5. 考场时间分配与做题顺序
笔试时间管理是很多人忽略的一环。120分钟看着充裕,但如果你在选择题上纠缠太久,编程题就很被动。我自己的体感是:选择题平均每题1.5分钟,超过这个时间就要先标记跳过;编程题先花5到8分钟读题和构思,再花15到20分钟写代码和调样例。这个节奏基本能保证三题都有时间看。
5.1 适合大部分人的答题节奏
推荐的顺序是先做编程题,再做选择题,或者反过来,但核心原则只有一条:优先保证"确定能拿到的分数"落袋。如果你选择题基础好,可以先快速过一遍选择题,把难题标记出来;如果你编程题思路快,就先把三道题都扫一眼,判断难度梯度,然后从最容易的那道开始写。
这里要说一个很多人会犯的错误:看到第二题像动态规划,就花了40分钟死磕,结果第三题其实是一道简单的二分答案,白白丢分。正确做法是拿到题目后先用两分钟把三道题都看完,在心里标记"这题我有思路、这题要想想、这题大概率没戏",然后再安排时间。特别是第三题如果是图论题而你不熟悉,就不要硬刚,把时间留给前两题的完善。
5.2 考试中的常见失误
我帮同学复盘过多次笔试,发现失分点往往不在"不会做",而在"提交前没有检查这四件事":
- 输入范围是否可能超int,需要用long long
- 数组下标是否越界,特别是状态转移时访问了dp[i-1]和dp[i-k]
- 输出格式是否严格一致,多一个空格、少一个换行都可能导致WA
- 是否忘记处理空输入或极端用例,比如n=0、字符串为空
这四条是笔试平台上最容易踩的坑。还有一个细节是,在线IDE里自己测试时,不要只测题目给的样例,要自己构造几个边界用例,比如最大数据量、重复元素、全零数组等。很多时候样例过了但WA,就是因为边界用例没有覆盖到。
6. 笔试后的复盘与下一阶段规划
笔试结束不等于这件事就翻篇了。我会建议你在考后48小时内,趁记忆还新鲜的时候做一次系统复盘,把每一道题都重新记下来,重点记录当时的卡点和最终解法。这些复盘笔记不仅是后续面试的准备素材,也是判断自己是否适合继续投递这个岗位的依据。
6.1 如何从笔试中提取有效信息
判分结果还没有出来时,你应该先自己对一遍答案。笔试题库虽然不公开,但编程题的思路和选择题的知识点大多是常见的,网上通常能找到类似的题目解析。复盘时不要只记"这题我不会",要记"我不会的原因是什么"。是状态转移没推出来?是数据结构不熟?还是题目读漏了条件?把原因分类,下一步的复习才有方向。
我复盘时用得比较顺手的模板是这样:标题、考察知识点、我的解法和最终结果(AC/部分通过/未提交)、标准解法步骤、卡住的时间点、同类题目3到5道。不要小看"卡住的时间点",它能帮你看清自己是阅读能力弱还是算法能力弱。比如你发现每次都在动态规划的状态定义上卡住,那就说明你缺的是"定义状态的直觉",需要大量刷DP相关的题,而不是漫无目的地刷题。
6.2 面试准备的衔接
如果笔试顺利通过,接下来就是面试环节。B站的面试一般有多轮,算法方向的面试官可能会以笔试卷面为基础追问,比如"你当时第三题为什么没有写出最优解"或者"如果数据量翻10倍,你的方案还成立吗"。所以笔试复盘不仅是给自己看,还要做好被追问的准备。
面试中的手撕代码和笔试的差别在于,面试官更看重你思考过程中的交流与表达。即使最终代码没写完,如果你能清晰地讲出状态定义和转移方程的推导思路,也会是加分项。这一点和笔试完全不同:笔试看提交结果,面试看思维过程。所以从笔试结束后,就要有意识地练习"边写边讲"的状态,把每道题从题目描述到复杂度分析都说顺溜。
从备考节奏上,我给应届生的建议是:把力扣高频题和热门算法(排序、搜索、DP、图论)刷熟,控制在看到题目能快速分类的程度;再花三分之一的时间准备机器学习基础,多看看逻辑回归、SVM、GBDT、过拟合和评估指标这些深度与广度平衡的知识点。
热门热搜词里出现的"粒子群算法""模拟退火""卡尔曼滤波"这类话题,在校招笔试中通常不会作为编程题出现,但在某些研究型岗位的简答题或后续面试里可能被问到。如果你有余力,建议了解一下它们的核心思想和适用场景就够了,不用花大量时间手推公式。B站算法岗位的业务导向决定了一个候选人只要算法基本功扎实、机器学习基础概念清楚,就已经能满足大部分笔试的筛选要求。与其纠结冷门算法,不如把高频考点的精度提上去。