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

资讯详情

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

2020B站校招算法笔试卷复盘:从KMP到背包问题的高频考点全解析

2020B站校招算法笔试卷复盘:从KMP到背包问题的高频考点全解析 2020年我完整跟了一遍哔哩哔哩校园招聘算法岗的笔试卷那套题给我的感觉是它比纯互联网大厂的卷子更杂比传统软件公司的卷子更活。这背后其实和B站的内容生态有直接关系——一个以UGC视频、弹幕文化、社区互动为核心的平台算法工程师面对的问题从来不是纯推荐或者纯搜索而是内容理解、用户画像、分发策略、社区治理等多个维度同时上阵。所以这套算法笔试卷并不是单纯考你背了多少数据结构而是看你在有限时间里能不能把基础算法用熟、用准、用出边界感。这篇文章我想把试卷的整体结构、高频考点、典型题解法和备考思路完整拆一遍。无论你是正在准备视频行业算法岗的应届生还是想检验自己基础算法功底的工程师这篇复盘应该都能给你一些有价值的参考。1. 先给这套试卷定个位它不是难是宽1.1 视频社区算法岗的人才画像B站的算法岗和电商、网约车、金融风控这类公司的算法岗表面上考察的科目差不多但底层逻辑差异很大。做交易类业务算法要围绕转化率、GMV、风险损失来建模做内容社区算法要理解的是内容质量、用户兴趣、社区氛围、创作者生态。这就决定了笔试命题时出题人不会只盯着你是不是会写Transformer而是更在意你计算机基础扎不扎实、能不能快速把问题抽象成算法模型。2020年这套卷子给我最直观的感觉是选择题覆盖面非常广编程题难度整体控制在LeetCode中等水平但每一道题都留了坑。它不是靠偏题怪题来拉开差距而是靠基础题里的细节和边界条件来筛人。这其实很符合内容平台的需求——算法工程师每天都要和大量真实、嘈杂、充满异常的数据打交道边界感比炫技重要得多。1.2 线上笔试环境对做题策略的影响这一届校招正赶上笔试全面线上化牛客网、赛码网这类平台成为主战场。线上笔试和纸质卷最大的区别是你不能在纸上画草图、写写划划所有思考都得在脑子里完成其次编程题的输入输出处理变得更加重要很多人不是不会解题而是挂在解析输入上。我在复盘这套试卷时把这作为一条主线做题策略不只是会做还包括在线上评测系统里做对。比如选择题部分很多人因为不熟悉多选少选不得分的规则丢分编程题部分有人输出格式差了换行就整题零分。这些在复盘时都得纳入考虑。2. 试卷结构全景选择题和编程题各自承担什么角色2.1 选择题覆盖的知识模块2020年这套试卷的选择题部分正常题量在20到30之间题型以单选为主、多选穿插。覆盖的知识模块基本可以分成四块数据结构与算法、计算机基础知识、机器学习基础、逻辑推理与数学。这里面数据结构与算法占比最高大概能到40%机器学习基础差不多25%计算机网络和操作系统加起来20%剩下的是数学和逻辑题。我整理了这套卷子里最常出现的考点做了一个梳理表知识模块具体考点出现频次数据结构栈与队列特性、二叉树遍历、哈希冲突处理、堆的调整过程高频算法KMP的next数组、排序算法稳定性、贪心与DP辨析、二分查找边界高频机器学习过拟合与正则化、精确率/召回率/F1、梯度下降变体、特征工程中高频操作系统进程线程区别、死锁条件、虚拟内存、页面置换算法低频计算机网络TCP握手、HTTP状态码、DNS解析流程低频数学逻辑概率计算、排列组合、逻辑推理中频从考点分布能看出一个趋势B站招聘算法岗并不指望你在笔试阶段就展现出对深度学习框架的精通而是先把CS基础这层地板铺好。机器学习相关的题也偏基础不会直接让你推导Transformer的注意力公式但会问你L1和L2正则化哪个更容易产生稀疏解类别不平衡怎么处理这类实战问题。2.2 编程题的难度阶梯编程题部分一般有3到4道难度是阶梯式上升的。第一题通常是字符串或简单模拟属于送分题但送分不等于白给往往设置了输入格式的坑第二题和第三题是重点得分区动态规划、贪心、双指针都可能出现最后一题如果出现往往是图论或复杂DP给全场最顶尖的那批人区分度用的。我复盘时发现一个有意思的现象这套卷子的编程题很少直接贴一个最长回文子串或者两数之和这种原题而是会套一层业务壳。比如会问根据用户的连续观看记录找出最长的无重复兴趣标签序列本质上是LeetCode第三题无重复字符的最长子串的换皮。所以如果你刷题只背原题答案不理解解法背后的抽象逻辑考场上很容易被这层壳吓住。3. 高频考点硬核拆解KMP、排序、贪心与动态规划3.1 KMP的next数组一字一句推演abacaba热搜里关于模式串pabacaba的next数组求解是一个非常经典的考点也是B站这类笔试选择题里出现频率很高的题。很多人对KMP的理解停留在背代码一旦next数组定义略作调整就懵了。这里我完整推一遍。先明确一个常用的定义next[i]表示模式串p[0..i]这个子串中最长相等前后缀的长度不包含子串自身。比如p[0..0]a它的前缀集合和后缀集合都是空集不含自身所以next[0] 0。我们一步一步看p abacabai 0子串a最长相等前后缀长度为0next[0]0i 1子串ab前缀有a后缀有b不相等next[1]0i 2子串aba前缀有a,ab后缀有ba,a最长相等的是a长度1next[2]1i 3子串abac前缀a,ab,aba后缀bac,ac,c没有相等的next[3]0i 4子串abaca前缀a,ab,aba,abac后缀baca,aca,ca,a最长相等为a长度1next[4]1i 5子串abacab注意看前缀a,ab,aba,abac,abaca后缀bacab,acab,cab,ab,b最长相等的是ab长度2next[5]2i 6子串abacaba前缀最后几个是abacab,abaca,abac,aba,ab,a后缀是bacaba,acaba,caba,aba,ba,a最长相等的是aba长度3next[6]3所以next数组为{0, 0, 1, 0, 1, 2, 3}。这里推荐用next[i]表示前i个字符组成的子串的最长相等前后缀长度也很常见这种定义下数组整体会往后错一位。刷题时一定要先看题目给的定义否则同样的字符串可能得出不同的数组。我当年在这个考点的建议是不要死记结论考场上花30秒手推一遍更稳。3.2 排序算法选择题里藏着的坑排序算法是选择题的常客而且B站这套卷子特别喜欢在稳定性和时间复杂度细节上做文章。直接贴一个对比表方便你自检排序算法平均时间复杂度最坏时间复杂度空间复杂度稳定性冒泡排序O(n²)O(n²)O(1)稳定快速排序O(n log n)O(n²)O(log n)不稳定归并排序O(n log n)O(n log n)O(n)稳定堆排序O(n log n)O(n log n)O(1)不稳定插入排序O(n²)O(n²)O(1)稳定希尔排序O(n^1.3~1.5)O(n²)O(1)不稳定选择排序O(n²)O(n²)O(1)不稳定光背这张表还不够真题往往会这样问对近似有序的数组以下哪种排序算法性能最好答案是插入排序因为它的最好时间复杂度是O(n)几乎有序时接近线性。再比如归并排序为什么是稳定的而快速排序不是这就要理解底层操作归并时遇到相等元素先取左半部分所以稳定快排的partition交换过程中相等元素的相对顺序可能被打乱。还有一类题是给一个中间状态问这是哪种排序的第几趟结果。比如第一趟排序后最小的元素被放到了最前面但其他元素相对顺序不变这是冒泡排序的特征如果是最小元素放最前面但其他元素顺序可能改变那就是选择排序。这类题没有捷径只能靠理解每轮排序做了什么。3.3 贪心和动态规划同一个场景两种解法选择题里非常爱考贪心和DP的辨析而且出题人很鸡贼经常给一个可以用贪心解、也可以用DP解的场景问你哪个对。我复盘到的经典例子是找零钱问题。如果硬币面额是1, 5, 10, 25这种贪心策略每次取不超过剩余金额的最大面额一定正确因为这套面额设计满足贪心选择性质。但如果面额换成1, 3, 4要找6块钱贪心会先取4剩下2只能取两个1一共3枚而最优解是取两个3一共2枚。这种场景就只能用动态规划。动态规划的状态转移方程是dp[i] min(dp[i - coin[j]] 1)其中coin[j]是硬币面额。如果题目再进一步问你能不能输出具体的找零方案那还要加一个path数组记录每一步选了哪枚硬币。从这里能看出笔试选择题里的算法题核心不是考察你能不能写出代码而是考察你知不知道什么情况能用贪心、什么情况必须上DP。判断标准也很朴素局部最优能不能推出全局最优能不能找到反例。平时刷题时多问自己一句这题我为什么用DP不用贪心比多刷十道题管用。4. 编程题实战典型题解法和考场上的边界处理4.1 字符串题把无重复最长子串用到业务场景前面提到了这套卷子喜欢给算法题套业务壳最典型的就是字符串处理。我这里写一个通用解法大家练的时候一定要把模板吃透。假设题目变成给定一个字符串表示用户连续观看的视频标签输出最长的没有重复标签的连续子串长度。这个壳子剥掉后就是LeetCode第三题。def length_of_longest_substring(s: str) - int: # 用哈希表记录每个字符最近一次出现的位置 pos {} left 0 max_len 0 for right, ch in enumerate(s): if ch in pos and pos[ch] left: # 如果当前字符在滑动窗口内出现过把左边界移到上次出现位置的下一个 left pos[ch] 1 pos[ch] right max_len max(max_len, right - left 1) return max_len这段代码有两个必考的边界点。一是pos[ch] left这个条件如果少了它遇到窗口外的历史位置也会错误地移动左边界二是left指针更新后max_len要基于新的窗口长度计算不能拿旧的窗口去更新。我在牛客这类平台刷题时发现很多人会问用set能不能做。能但用set的写法需要做删除操作复杂度虽然是O(n)实际跑起来比哈希表pos版本慢不少而且在线上笔试环境里极端长字符串用例有超时风险。这里建议直接写哈希表版本。4.2 0-1背包的一维优化从二维DP到一维数组背包类DP是算法笔试卷里的常客B站这套卷子里也出现过。0-1背包的标准状态定义是dp[i][j]表示前i件物品放入容量为j的背包能获得的最大价值转移方程为dp[i][j] max(dp[i-1][j], dp[i-1][j-w[i]] v[i])考场上必须会的优化是滚动数组压缩到一维。因为dp[i]只依赖dp[i-1]所以可以用一维数组从后往前更新dp [0] * (capacity 1) for i in range(n): for j in range(capacity, w[i] - 1, -1): dp[j] max(dp[j], dp[j - w[i]] v[i])这里最重要的一个细节是内层循环必须从大到小遍历。如果从小到大dp[j - w[i]]可能已经被当前这一件物品更新过相当于一件物品被用了多次那就变成了完全背包。这个细节几乎每年笔试都会有人踩值得反复提醒自己。如果是完全背包内层循环改成从小到大即可for j in range(w[i], capacity 1): dp[j] max(dp[j], dp[j - w[i]] v[i])两种背包只差一个遍历方向但含义天差地别。建议大家刷到这类题时把二维转移方程、一维优化、遍历方向三个层次一次性串起来理解而不是分别背。4.3 线上笔试的输入输出陷阱说真的编程题写不出解法只是输的一种方式还有一种是写出了解法却因为输入输出处理不对而零分。我复盘2020年的线上笔试时发现环境用的是标准输入输出也就是要自己写sys.stdin或input()读取。这里有几个高频坑。第一个坑是多行输入。题目可能第一行给n第二行给n个整数。如果只用input()读一次就会少读一行import sys def main(): data sys.stdin.read().strip().split() if not data: return n int(data[0]) arr list(map(int, data[1:1 n])) result solve(arr) print(result) if __name__ __main__: main()一次性把标准输入全部读进来再解析是线上笔试最稳的方式能避免换行符、行尾空格等问题。第二个坑是输出格式。有些题目要求每个结果占一行有些人把所有结果用空格隔开输出系统比对字符串就会判错。遇到这类题先把构建结果列表最后用\n.join(...)拼接成整体输出。第三个坑是Python递归深度。如果编程题需要用递归处理、而且数据规模到10的5次方以上默认递归深度会报RecursionError非递归写法或者增加递归深度限制sys.setrecursionlimit(1 25)要提前想好。5. 机器学习与智能算法B站笔试里的算法不止数据结构5.1 机器学习基础考点过拟合、评估指标、类别不平衡如果岗位明确是算法工程师、推荐算法工程师那笔试卷里一定会出现机器学习基础题。B站这套卷子涉及的机器学习考点我复盘之后总结了几个高频方向。过拟合的识别与处理是必考的。题目会给你一个训练集准确率98%、测试集准确率72%的场景问可能是什么问题、应该怎么解决。答案很明确过拟合解决手段包括增加数据量、降低模型复杂度、加正则化、早停、Dropout。这里容易混淆的是正则化类型L1会产生稀疏解、可以用于特征选择L2会让权重趋向0但不会精确等于0。评估指标是另一个高频方向。推荐场景中正负样本往往极不平衡精确率和召回率比准确率更有参考价值。公式要熟精确率 TP/(TPFP)召回率 TP/(TPFN)F1是精确率和召回率的调和平均数。会出一道简单的计算题测试集100个样本正样本20个模型预测出15个正样本其中12个是真阳性问精确率和召回率是多少。答案是精确率 12/15 0.8召回率 12/20 0.6。这种题没有技巧就是熟练。类别不平衡的处理在B站这种内容平台很有实战意义因为正反馈和负反馈天然不均衡。常见方案过采样少数类、欠采样多数类、调整类别权重、使用Focal Loss、用AUC等对不平衡不敏感的指标。知道这些属于话题型考点不需要你推导公式但至少要答得出大致方向。5.2 粒子群算法这类非主流考点怎么准备热搜里出现了粒子群算法原理这其实也是算法笔试选择题的一个可能方向。粒子群算法PSO属于群体智能优化算法和遗传算法、模拟退火算法并称三大经典启发式算法。在刷题时很多人会忽略这类知识因为他们更关注确定性算法。B站这类业务场景中很多问题并不是标准解析解能解决的比如推荐策略中的多目标参数调优、视频转码参数组合寻优都可能用到这类启发式算法。所以笔试卷中出现粒子群算法的选择题并不突兀。粒子群算法的核心思想是模拟鸟群觅食每个候选解是一个粒子粒子有位置和速度每次迭代根据个体历史最优位置pBest和群体历史最优位置gBest来更新速度再更新位置。关键公式是速度更新v[i] w * v[i] c1 * r1 * (pBest[i] - x[i]) c2 * r2 * (gBest - x[i])其中w是惯性权重c1、c2是学习因子r1、r2是[0,1]之间的随机数。位置更新就是x[i] x[i] v[i]。选择题如果考PSO一般就是问粒子群算法中粒子的速度和位置更新依赖哪些量或者惯性权重w的作用是什么。前者答案是个体历史最优和群体历史最优后者答案是平衡全局搜索和局部搜索的能力。这类题不需要写代码把概念理清就够了。复习建议是把遗传算法、模拟退火、粒子群三个算法的核心思想、参数、优缺点做成一张对比表考前几天过一遍。6. 复盘之后给后来人的几点实在建议6.1 刷题要有业务抽象意识这套卷子给我最大的教训是B站这种内容平台的算法笔试不满足于考原题。同样的知识点它会包装成用户观看序列弹幕情感标签内容推荐候选集等业务场景。平时刷LeetCode时我建议每做完一道题停下来想一步这个算法在公司业务里会出现在哪里比如滑动窗口现实中就是用户在一定时间窗口内的行为序列分析单调栈就是在视频序列中找下一个热度更高的视频拓扑排序就是课程依赖关系/内容推荐依赖关系。有了这层业务抽象能力考场上看到任何披着业务壳的题你都能快速剥壳还原成核心算法模型。6.2 错题本比题量重要我不是反对大量刷题而是反对无脑刷。同样是刷200道题有人是靠AC数量堆上去的有人是靠错题本迭代上去的后者的效果完全不一样。建议给常见的错误分类边界条件遗漏空数组、单元素、越界、数据结构选择失误该用哈希表却用了列表、贪心和DP误判、输入输出处理不当。每次笔试或模拟考后更新一次错题本考前重点翻错题本而不是重新刷题。6.3 前30分钟的选择题策略线上笔试的时间分配直接决定编程题能不能做完。建议先快速扫一遍选择题遇到需要复杂计算的先标记跳过把时间留给后面的编程题。我见过太多人卡在选择题的某道概率题上算半天最后编程题没时间写。选择题一道也就2到4分编程题一道至少20到30分这个账要算清楚。6.4 有条件的话模拟一次真实笔试环境很多人平时在IDE里刷题很顺一上牛客的在线评测系统就各种不适应。建议考前至少完整模拟一次开计时器不开代码补全不查API文档全程用标准输入输出一次性提交通过。这一套流程走下来能暴露很多平时发现不了的问题。这套2020年的B站校招算法笔试卷整体难度放在今天看依然有参考价值。它不考验记忆力和偏题储备考验的是你在有限时间内对基础算法的熟练度和判断力。准备这类笔试与其焦虑还有多少题没刷不如把基础模块一个一个夯实KMP能手推next数组排序能说清稳定性和复杂度贪心和DP能准确辨析背包模板能闭眼写对遍历方向机器学习基础概念能快速反应。这几板斧在考场上比任何花哨技巧都管用。
返回列表