ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

B站算法岗笔试复盘:KMP、TopK与工程落地全解析

2026/8/31 14:42:31 拓冰建站 浏览量
B站算法岗笔试复盘:KMP、TopK与工程落地全解析 1. 写在前面一套让你“现出原形”的笔试题先说个人背景我是2019年秋季参加B站算法岗笔试的投的是推荐方向。当时点开这套题的时候第一感受是“题目量不大但每一道都踩在算法基本功的命门上”。和其他大厂动辄四五道编程题、两小时码到手指抽筋的风格不同B站这套题更偏向“数据结构 算法原理 工程落地”三合一选择题考概念辨析编程题考代码实现最后还有一道综合设计题整体难度属于中等偏上但区分度极高——基础扎实的人40分钟能交卷基础不牢的人可能卡在第一道编程题的边界条件上。这篇文章不是单纯贴一份“历年真题答案”而是想以这套题为引子把算法笔试中真正重要的东西拆开揉碎KMP的next数组为什么会写错、堆排序为什么能用来解决TopK、贪心算法在什么条件下才敢用、机器学习算法题该从哪个角度切入以及笔试现场常见的翻车点。如果你正在准备算法岗秋招或者只是想系统过一遍核心算法这篇文章应该能帮你少走一些弯路。另外说明一下由于时间比较久当年的题目我没有完整留存下面涉及的具体题目是基于我记忆中的题型和考点重构的重点在于题目背后的知识点和解题思路这恰恰是准备笔试最有价值的部分。2. 笔试题整体结构与考查方向2.1 一套题覆盖了哪些算法板块这套题的题型分布大致是8道不定项选择题、2道编程题、1道算法设计题考试时长90分钟。听起来题量不算大但每道选择题都有“坑”每道编程题都要求完整通过测试用例设计题更是开放到让你摸不着头脑——不给你标准答案只给你一个业务场景看你如何拆解。从考查范围来看可以分为五个板块数据结构基础数组、链表、栈、队列、树、图的存储与遍历经典算法排序、KMP、贪心、动态规划、二分、快速幂机器学习/深度学习基础KNN、聚类、损失函数、梯度下降、常见模型对比算法工程能力代码实现、边界处理、复杂度分析、和海量数据场景结合算法设计思维针对具体业务抽象数学模型给出可落地的方案为什么B站会这样设计我当时面完和几个朋友交流一致的判断是B站的技术栈非常吃“工程落地能力”。算法岗不是发paper的岗位而是要写线上服务、处理用户行为数据、优化推荐和搜索效果。所以笔试不考偏题怪题而是考那些“面试官自己写代码时也会用的东西”——比如手撕一个快排、算一个KMP的next数组、在海量数据里找TopK。这套题的本质是筛选“代码功底靠谱、算法理解不浮于表面”的人。2.2 高频考点背后的逻辑为什么考这些先说选择题里的高频考点。数据结构与算法部分排序算法的稳定性和复杂度、哈希冲突的解决办法、二叉树的遍历序列推导、图的遍历与最短路径这些几乎是必考的。原因很简单排序和哈希是工程中使用频率最高的两类基础结构二叉树的遍历是递归思维的试金石图算法则是后续考察搜索、推荐、路径规划等场景的底层支撑。B站作为内容平台推荐系统重度依赖用户行为序列和内容关系图图相关的算法功底扎实的人业务上手会快很多。机器学习算法部分KNN、K-Means、逻辑回归、决策树是选择题常客。这些模型虽然经典但它们的假设条件、优缺点、适用场景经常被混淆。比如K-Means对初始值敏感、需要预先指定K值KNN是惰性学习、预测时需要全部训练样本参与距离计算。这些细节在工程选型时直接决定模型能不能用、效果好不好所以笔试专门拿出来考不是刁难而是基本功。高频考点还有一个隐藏逻辑——引导你去想“为什么”。比如排序稳定性为什么要单独考因为稳定排序在多次排序场景下有实际意义比如先按时间排序再按点击量排序如果第二次排序不稳定第一次排序的结果会被打乱。这种“能说出来龙去脉”的理解深度是笔试真正想测试的。3. 选择题核心考点深度解析3.1 数据结构与经典算法从KMP到堆排序选择题里有一道KMP的题让我印象很深题目是在KMP算法中对于模式串pabacaba计算其next数组。很多人看到KMP就头大因为next数组的定义在不同教材里都有两三种版本——有的next[i]表示“i位置之前的子串的最长相等前后缀长度”有的表示“失配后跳转的位置”。我当时用的定义是next[i]表示模式串中从0到i-1的子串的最长相等前后缀长度且next[0] -1。按这个定义pabacaba我们逐个推导i0next[0] -1i1子串a没有真前后缀next[1] 0i2子串ab前缀a、后缀b不相等next[2] 0i3子串aba最长相等前后缀是a长度1next[3] 1i4子串abac前缀a、ab、aba后缀c、ac、bac无相等next[4] 0i5子串abaca前缀a、ab、aba、abac后缀a、ca、aca、baca最长相等前后缀是a长度1next[5] 1i6子串abacab前缀a、ab、aba、abac、abaca后缀b、ab、cab、acab、bacab最长相等前后缀ab长度2next[6] 2所以next数组为[-1, 0, 0, 1, 0, 1, 2]。这里有一个非常容易出错的点i6的时候最长相等前后缀是ab而不是a因为字符串前缀的“ab”和后缀的“ab”确实相等。很多人算到这一步会偷懒看到前一个位置是1就直接填1结果整个数组就错了。KMP的next计算是一个动态规划过程每一个位置都要老实去匹配不能拍脑袋。堆排序也考了一道不是让写代码而是问“用堆排序找出n个元素中最大的k个元素时间复杂度是多少”。正确思路是维护一个大小为k的小顶堆遍历n个元素每次与堆顶比较如果比堆顶大就替换并调整堆最终堆里就是最大的k个元素。建堆复杂度O(k)每次替换调整O(log k)最多替换n-k次总复杂度O(n log k)。这个方案在海量数据场景下几乎是唯一解因为内存装不下全部数据只能一次读一个用堆保留前k个。这道题背后其实在考“外部排序”和“流式处理”的思想。还有一道关于二分查找的题问的是在一个有序数组中查找第一个大于等于目标值的位置。这是二分查找的边界变形很多人会写错low和high的更新条件。正确写法是int lower_bound(vectorint nums, int target) { int l 0, r nums.size(); while (l r) { int mid l (r - l) / 2; if (nums[mid] target) { l mid 1; } else { r mid; } } return l; }注意这里r的初始值是nums.size()而不是nums.size()-1循环条件是l r更新时r mid而不是r mid - 1。这套写法是左闭右开区间很多刚刷题的人不习惯但它是STL中lower_bound的标准实现笔试中直接背下来用就行。3.2 机器学习/深度学习概念辨析与陷阱这套题的选择题里机器学习占比不低我印象中至少有3道。一道考KNN的“三要素”距离度量、K值选择、分类决策规则。很多人只记得“KNN是惰性学习”但K值选择的影响说不清楚——K太小容易过拟合噪音点对结果影响大K太大又会让远处样本拉低局部特征边界变模糊。实际调参时一般用交叉验证选K通常取奇数避免平票这在笔试和面试中都是常考点。另一道考K-Means算法的特点。选项里有个“K-Means能自动确定聚类数K”这明显是错的但确实有人选。K-Means必须预先指定K而且对初始中心点敏感不同初始化可能收敛到不同局部最优。解决办法是K-Means初始化时让中心点尽量分散先在样本中随机选第一个中心然后计算每个样本到最近中心的距离按距离平方加权概率选择下一个中心。这个改进在工程中几乎是标配如果你在笔试答案里写出K-Means会让面试官觉得你有实战经验而不只是在背课本。还有一道深度学习相关考损失函数与激活函数的匹配。选项涉及均方误差MSE配Sigmoid、交叉熵配Softmax等。这里的关键是MSE配Sigmoid在反向传播时梯度会包含σ(z) σ(z)(1-σ(z))这一项当σ(z)接近0或1时梯度趋近于0收敛极慢而交叉熵配合Softmax的梯度形式简洁不存在饱和区梯度消失的问题。这个知识点在题目里出现说明B站比较看重候选人对模型训练细节的理解而不仅仅是会调用框架。这类选择题的备考策略并不复杂把经典模型的假设、损失函数、优化方法、适用场景、优缺点整理成对比表格逐一弄清基本就能覆盖。我当时把KNN、K-Means、朴素贝叶斯、逻辑回归、决策树、SVM、随机森林、GBDT、CNN、RNN都过了一遍重点放在“为什么这样设计”和“适用场景差异”上事实证明非常高效。4. 编程题实操从读题到AC的完整过程4.1 编程题一海量数据TopK问题题目大意是给定一个包含n个整数的文件n可能上亿内存只有几百MB求其中最大的K个数K远小于n并分析算法复杂度。这题就是上面选择题里堆排序的实际应用但笔试现场要写出完整代码而且要考虑文件读取的IO效率。我的实现思路分三步第一步明确内存约束。假设文件里是4字节intn1亿全部读入内存要400MB显然超了。所以不能全部load进来。第二步用最小堆维护TopK。堆的大小为K用STL的priority_queue实现。读取文件中的每个数如果堆的大小小于K就直接入堆如果堆已满且当前数大于堆顶就弹出堆顶、压入当前数。这样最终堆内就是最大的K个数。第三步处理输出。把堆中元素依次弹出放入vector然后reverse得到降序序列。核心代码#include bits/stdc.h using namespace std; vectorint topK(ifstream in, int K) { priority_queueint, vectorint, greaterint minHeap; int num; while (in num) { if ((int)minHeap.size() K) { minHeap.push(num); } else if (num minHeap.top()) { minHeap.pop(); minHeap.push(num); } } vectorint res(K); for (int i K - 1; i 0; --i) { res[i] minHeap.top(); minHeap.pop(); } return res; }这段代码有两个坑笔试时容易翻车。第一个坑是堆内元素个数还没达到K时如果直接跟堆顶比较堆顶不存在会崩所以必须先判断size。第二个坑是输出顺序堆弹出是从小到大要得到降序必须倒序填充。别看这两个点简单考场上紧张起来真有人栽在这上面。复杂度分析遍历n个数需要O(n)次读取每次堆操作O(log K)总时间O(n log K)空间O(K)。如果是多路归并外部排序也能解决问题但复杂度更高。在面试中我还会多提一句如果K也很大比如K 10万堆的常数开销就比较明显可以考虑分段排序后归并但笔试标准答案就是小顶堆方案。4.2 编程题二KMP字符串匹配第二道编程题是经典KMP题目给一个主串s和一个模式串p要求输出模式串在主串中所有出现位置的起始下标主串长度不超过1e6模式串长度不超过1e5。这题放在笔试里考察的就是“你能不能在不查资料的情况下一口气写对KMP”。我现场写的是标准KMP分两步先求next数组再做匹配。这里给出完整实现注释尽量详细#include bits/stdc.h using namespace std; vectorint buildNext(const string p) { int m p.size(); vectorint next(m, -1); int k -1; for (int i 1; i m; i) { while (k ! -1 p[k 1] ! p[i]) { k next[k]; // 回退到上一个可匹配位置 } if (p[k 1] p[i]) { k; } next[i] k; } return next; } void kmpSearch(const string s, const string p) { vectorint next buildNext(p); int n s.size(), m p.size(); int q -1; // 已匹配前缀的最后一个下标 for (int i 0; i n; i) { while (q ! -1 p[q 1] ! s[i]) { q next[q]; } if (p[q 1] s[i]) { q; } if (q m - 1) { cout i - m 1 endl; // 匹配起始位置 q next[q]; // 继续查找下一个匹配 } } }建议大家重点理解两处回退逻辑。第一处是构建next数组时的k next[k]很多人看不懂这行。它的物理含义是当前前缀的某个后缀与模式串前缀的某个前缀相等如果直接在下一字符上失配就回退到更短的“已匹配前缀”继续尝试。这本质上是动态规划 回溯但回溯路径被next数组缓存了所以线性。第二处是匹配过程的q next[q]含义类似匹配成功后为了寻找下一个可能的匹配位置不能简单地把q清零而要把q回退到当前匹配前缀的最长相等前后缀位置因为主串当前位置的后面部分可能已经匹配了模式串的某个前缀。KMP的时间复杂度是O(nm)空间O(m)。对于1e6的主串这个性能是没问题的。如果写暴力匹配最坏O(n*m)在1e6 * 1e5的数据下直接超时。所以笔试考KMP本质上是考你“能不能识别出线性复杂度的必要性”。4.3 算法设计题推荐系统中的TopK召回设计题是开放式的我记忆中的场景是B站有海量视频每个用户有观看历史要求设计一个推荐召回方案在用户打开App时快速生成候选视频列表。这题没有标准答案但有几个关键得分点。第一个得分点明确召回和精排的分层架构。不能在几十万甚至百万级视频库上直接跑复杂排序要先做多路召回再用粗排/精排。常用召回策略包括基于用户观看历史的协同过滤ItemCF、基于内容标签的相似推荐、热门视频兜底、以及基于用户实时行为如刚看完某个视频的关联推荐。第二个得分点考虑冷启动。新用户没有历史行为需要靠热门榜单、分类偏好选择、或者编辑推荐来兜底。新视频没有观看数据需要靠内容标签匹配和探索策略比如给一小部分流量做试投来获得初始曝光。第三个得分点实时性。召回不是一次性算好而是要跟用户当前状态绑定。比如用户刚看完一个美食视频召回列表里应该立刻出现同类的其他美食视频这要求“基于最近行为的实时召回”具备毫秒级延迟通常用Redis存用户最近行为用倒排索引快速过滤候选。第四个得分点数据结构和算法落地。如果做ItemCF视频相似度矩阵可能很大但可以用“共同被观看的次数”做倒排索引加速热门视频全局共享一个缓存列表个性化召回结果也要缓存避免每次请求都全量计算。这正好对应前面选择题里的堆、哈希、倒排索引等知识点。设计题的评分思路我能从面试反馈中大致勾画出来。面试官说“不用给出完美方案但要想清楚每一步的输入输出和延迟预算”。所以我的建议是写设计题时不要一上来堆砌模型先画清楚数据流说清楚每一层的输入是什么、输出是什么、存储在哪、耗时多少。你先搭好工程骨架再往骨架里填充具体算法分数基本就有了。5. 各个算法热点的实操与延伸5.1 排序算法冒泡、快排、堆排的选择依据这套题虽然没考手写所有排序但围绕排序算法的选择题不少比如复杂度、稳定性、适用场景。我在备考时整理过一张排序算法速查表趁这个机会分享出来。算法平均时间复杂度最坏时间复杂度空间复杂度稳定性冒泡排序O(n²)O(n²)O(1)稳定选择排序O(n²)O(n²)O(1)不稳定插入排序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)不稳定实际工程里C的std::sort是快排 插入排序的混合体当递归深度超过阈值时改用堆排序当子数组较小时改用插入排序目的就是同时保证最坏情况复杂度和常数速度。而像TopK这种场景全排序是浪费的堆是更优解。如果你正在准备笔试我建议排序这块至少能手写快排、归并、堆排三种。快排最常考但边界条件非常容易写错。我自己的快排模板是void quickSort(vectorint nums, int l, int r) { if (l r) return; int i l, j r, pivot nums[l (r - l) / 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, l, j); quickSort(nums, i, r); }这个写法和教科书上的标准partition不太一样但更不容易写错而且能处理大量重复元素的情况三路划分的思想。笔试时我强烈建议用自己验证过的模板不要现场发挥因为发挥容易翻车。5.2 贪心算法与动态规划何时能用、何时不能用这套题里出现了贪心算法的选择题同时也有一道DP题我印象中是背包问题的变体。贪心和DP很多时候都是求最优解但适用条件不同。如果一道题具备“贪心选择性质”和“最优子结构”那么贪心是最高效的解法如果只有最优子结构而没有贪心选择性质就得用DP把子问题的所有解都枚举出来。经典的区间调度问题就是贪心的典型例子给定若干区间选尽可能多的互不重叠区间。贪心策略是每次选结束时间最早的区间因为结束得越早留给后面的时间越多。我当时笔试时看到这题脑子里过了一遍反证法就敢写假设最优解的第一个区间不是结束最早的区间把它替换成结束更早的区间后续区间不受影响所以替换后的解不差于最优解证毕。而像背包问题0-1背包必须用DP因为每个物品只有选和不选两种状态不能靠局部最优贪出来但完全背包却可以通过优化成一维数组DP来解决这里的“贪心”只是单调队列优化的一部分并不改变DP的本质。给一个简单可操作的区分方法如果你能证明“当前选择不会影响未来的可选空间”那大概率可以贪心如果选择会改变后续子问题的输入条件那大概率要DP。笔试现场没有时间做严格证明先用这个方法判断再用小样例验证。5.3 图算法从Dijkstra到二分图HK算法图相关的题目在这套题里出现的不算多但有一道关于最短路径的选择题。Dijkstra算法适用于边权非负的单源最短路径时间复杂度O((VE)log V)用优先队列实现。如果边权有负数Dijkstra就会失效——因为它每次贪心选当前距离最小的节点但负权边可能在后面“回头”更新更短路径。这种场景需要用Bellman-Ford或SPFA。但值得注意的是Dijkstra的贪心思想本身值得记住通过优先队列每次取出当前已知距离最小的节点进行松弛本质上也是“贪心 松弛”的模式。理解这一点你会发现很多图算法和上面说的经典贪心DP是一脉相承的。二分图HK算法Hopcroft-Karp在热搜词里出现了这类算法在秋招笔试中出现的概率不大因为写出完整实现的代码量大、考点深。但如果面试聊到推荐系统的用户-物品二分图匹配HK算法可以作为加分项提到它是对匈牙利算法的BFSDFS优化能把二分图最大匹配的复杂度从O(VE)降到O(E√V)。我建议准备面试时了解一下原理笔试则需要优先掌握Dijkstra、拓扑排序、并查集、最小生成树这几个高概率考点。5.4 机器学习与AI热门算法聚类、KNN、卡尔曼滤波这套题里机器学习相关选择题已经考了几个但我觉得有必要把几个容易出现理解偏差的算法再展开说说。KNN算法的三个核心能力点我在笔试后复盘时总结成了三条。第一分类通过多数投票决定类别第二回归通过K个近邻的均值或加权均值预测数值第三异常检测如果样本的K个近邻距离都很大说明它远离大多数样本可能是异常点。这三个能力对应KNN在不同任务中的用法面试官经常用“KNN能做哪三件事”这种开放式问题考察理解的全面性。聚类算法中K-Means虽然简单但写代码时经常有个隐藏坑初始中心点的选择。如果随机选到离群点聚类效果会明显变差。我在项目里用K-Means时一定会接K-Means初始化效果稳定很多。另外K-Means假设簇是凸的、大小相近如果数据分布是长条形或环形K-Means效果很差这时候应该考虑DBSCAN或谱聚类。这种“模型假设匹配数据分布”的意识是校招面试高频考点。卡尔曼滤波是另一个热搜词它不是在推荐算法里常用而是在信号处理和控制系统里常用。笔试里出现它的概率不大但如果你在项目里用过多传感器融合面试官很可能会顺着问卡尔曼滤波的原理。卡尔曼滤波的核心分为预测和更新两步先根据运动模型预测当前状态和协方差再利用观测值更新预测结果通过卡尔曼增益权衡预测和观测的可信度。它的本质是贝叶斯滤波在线性高斯假设下的闭式解。了解这个底层原理比背诵五个公式重要得多。5.5 粒子群算法、模拟退火等优化算法的作用这类启发式算法在这套笔试题里没有直接考但如果在设计题里需要用复杂优化提一嘴可以加分。粒子群算法PSO和模拟退火SA都属于无梯度优化方法适用于目标函数不可导甚至没有解析表达式的情况。粒子群算法模拟鸟群觅食每个粒子有自己的位置和速度根据个体最优和群体最优更新速度迭代逼近最优解模拟退火则以一定概率接受更差的解从而跳出局部最优。说实话算法岗笔试考这类算法的概率很低因为它们不是工程中高频使用的工具。但我在准备面试时还是整理过它们的适用场景比如推荐系统的超参数调优、资源调度问题、组合优化问题等。面试官如果问到“你用过哪些优化算法”能把这几个说清楚会显得你的知识面不局限于深度学习的反向传播。6. 常见问题与排查技巧实录6.1 笔试现场的5个“隐形杀手”我在刷笔试真题和真实笔试中踩过不少坑这里梳理出高频问题每个都是血泪经验。第一个隐形杀手是读题不仔细。笔试题通常会有一句“输出所有满足条件的下标从小到大排序”或“如果没有满足条件的输出-1”。很多人看到题目就开始写写完才发现漏了大条件只能返工。我自己的习惯是拿到题目先花1分钟划出输入范围、输出格式、特殊条件再动笔。第二个隐形杀手是边界条件。最常见的就是数组下标越界、K0、n1时程序崩溃。比如TopK问题里K0时priority_queue为空如果直接读top()会未定义行为。建议在代码开头加一段防御性判断。第三个隐形杀手是内存超限。有一道记忆中的题如果按照二维数组存图n到10万级别就爆内存了需要用邻接表或者边集数组。笔试时会给出时间和内存限制一定要先看数据范围再选择数据结构。第四个隐形杀手是复杂度估计错误。在1e6的数据规模下O(n²)的算法几乎必死在1e5规模下O(n²)可能侥幸过但O(n log n)才稳妥。所以写完代码后估算一下最坏情况下的运算量如果超过1e8就要考虑优化。第五个隐形杀手是代码模板不熟练。我见过太多人平时刷题很顺但上了笔试平台在没有IDE自动补全的情况下连快排都写不利索。建议考前一周专门在leetcode或牛客的模拟环境里练习不开IDE插件完全手打。6.2 从AC到高分设计题的答题模板很多算法岗候选人编程题能AC但设计题得分很低。我后来面试官反馈说评分时最看重的是两样东西一是能不能把模糊的业务问题转化成明确的输入输出二是方案有没有考虑延迟、容量和扩展性。我总结了一个能直接套用的设计题答题模板共三步。第一步场景拆解。把“推荐召回”“异常检测”“路径规划”这类业务描述拆成具体的输入输出。输入是什么数据数据量多大实时还是离线输出是什么精度要求多少延迟要求多少比如推荐召回输入是用户ID和最近行为序列输出是100个候选视频ID在线延迟要求200ms离线可以跑小时级任务。第二步方案分层。不要试图一个算法解决所有问题把流程分为离线计算层和在线服务层。离线层负责预处理、特征计算、模型训练在线层负责快速检索和排序。每一层都要说清用什么数据结构、什么存储介质、什么算法。第三步容错与兜底。热门方案缓存失效怎么办新用户没有数据怎么办候选集不足怎么办给出兜底策略比如热门榜兜底。这个步骤最容易被忽略但在面试官眼里恰恰是工程经验的分水岭。6.3 算法岗笔试准备建议最后给正在准备秋招的朋友几条实在建议都是我踩过坑后总结出来的。第一刷题用“题型归纳法”而不是“题海战术”。把常见题型按考点分类数组操作、链表、二叉树、图、DP、贪心、字符串匹配、排序、海量数据每类刷30到50道基本能覆盖笔试80%的场景。不要每天随机刷题那样效率很低。第二每道题做完后做三个复盘动作重写一遍核心代码直到不看答案能AC写下复杂度分析思考如果数据量扩大100倍要怎么改。这三个动作会让刷题价值最大化。第三机器学习方向的同学除了刷算法题还要把高频模型的原理过一遍。重点看损失函数、优化方法、正则化、偏差方差、过拟合、样本不平衡这些是选择题和交叉面最常考的内容。第四留出至少一周时间做整套模拟。按真实考试时间90分钟完成一套题包括选择题和设计题严格计时。模拟的环境越接近真实考场上的紧张感越低。7. 写在最后一道笔试背后的算法观这套B站2019秋招算法笔试题名义上是筛选候选人的工具但考题背后其实在强调一种“算法观”——算法不是背一堆公式和模板而是面对真实问题时能快速把它拆解成已知的数据结构和经典算法再根据约束条件时间、内存、数据规模选择最合适的实现。KMP的next数组也好TopK的小顶堆也好设计题里的多路召回也好本质都在考察这个能力。我个人在准备秋招和实际工作后的体会是笔试考的东西恰恰是工作中最常见的东西。推荐系统写线上服务时离不开排序、堆、哈希、倒排索引做特征计算时离不开K-means、KNN、embedding排查线上问题时又需要你对复杂度和数据结构有本能级的敏感。所以不要把笔试当任务它更像一次“算法内功”的体检帮你找到薄弱环节再逐一补齐。如果你正在准备算法岗笔试希望这篇内容能帮你少踩一些我踩过的坑。如果这套题你已经刷过不妨再回头看一遍可能你会发现当年觉得刁钻的题目其实背后都是一些很朴素的道理。