
快手2019年秋季校园招聘算法A卷这份试卷在当年可以说让不少投递算法岗的同学栽了跟头。我身边就有朋友考完出来直摇头说题目看着面熟一上手全是坑。到现在每年秋招还有不少人翻出这套题来刷把它当成大厂算法笔试的风向标之一。我自己也把这套卷子翻来覆去研究过好几遍今天就把这套试卷背后的考察逻辑、高频知识点的拆解方法、以及我当时刷题和带人准备时总结出来的实战经验一并整理出来给准备算法岗笔试的同学一个完整的参考。这篇文章不打算给你逐题报答案因为各家题库每年都在更新死记答案没有任何意义。我会从“这套试卷到底在考什么”出发把算法A卷背后那份筛选逻辑讲透再结合KMP、排序、贪心、动态规划、图论这些高频考点讲清楚每一类题在笔试里的变形套路和最容易翻车的细节最后聊一聊从这套卷子反推出来的备考节奏。无论你是刚开始准备校招的低年级同学还是马上要上战场的秋招选手这篇都能帮你把力气花在刀刃上。1. 快手算法A卷到底在考什么先读懂试卷的筛选逻辑很多同学拿到算法笔试卷子第一反应就是赶紧看题、赶紧敲代码恨不得把每道题都现场AC掉。但我的建议是拿到卷子先别急着动手花两分钟把整张卷子扫一遍搞清楚这十五到二十分钟里出题人到底在测你什么。1.1 算法A卷的定位基础能力还是综合能力“A卷”这个词在快手的秋招体系里不是随便标的。一般来说多套并行的笔试试卷A卷往往是面向算法工程师、机器学习工程师等偏研究型岗位的通用卷。它不会只考纯工程代码能力也不会只考模型调参而是一条线串起“数据结构与算法基本功 概率统计/机器学习基础 场景应用题”三个板块。这和纯后端岗位的笔试卷有明显区别后者更偏重工程实现、系统设计而A卷里你会看到大量和算法复杂度、模型原理、策略优化相关的题目。从历年考生反馈和公开的面经来看快手算法A卷的题型大致分成三类选择题、编程题、以及少量问答或设计题。选择题部分覆盖面很广从排序算法的稳定性到底层数据结构的时间复杂度再到机器学习中的偏差方差、损失函数都会涉及。编程题部分通常有两到三道难度梯度拉开得非常明显第一道是让你找找手感的热身题第二道才是真正区分层次的核心题第三道往往带有一定的竞赛色彩用来筛出真正有算法功底的候选人。1.2 出题人要筛选的是什么人要想在这套卷子上拿到高分关键不是把题海战术做到极致而是理解出题人的心理。快手这类短视频平台算法团队的核心工作场景是什么是推荐系统、内容理解、视频编解码优化、审核策略、增长实验。日常工作中你面对的不是一本教科书而是大规模数据流和实时反馈。因此笔试题目设计时会特别看重两样东西一是你把抽象问题转化成可计算模型的能力二是你对算法效率的敏感度。举个很典型的例子同样是字符串匹配题朴素解法写出来只有几行时间复杂度是O(n*m)但如果数据规模到了10的6次方级别这种解法直接超时。出题人不会明说“请用KMP”他只会把数据范围悄悄写在那里看你能不能敏锐地意识到需要更优的算法。很多同学栽跟头不是因为不会KMP而是根本没意识到这题需要KMP。这就是筛选逻辑不只是考你会不会更是考你在真实环境中能不能做出正确的技术判断。1.3 那批热搜词背后的信号我注意到这几年和“快手算法笔试卷”关联的热搜词里反复出现粒子群算法、KMP算法、音频重采样算法、规则引擎Rete算法、PID算法、卡尔曼滤波、BM25算法、图像锐化拉普拉斯算法等等。这些词暴露了一个重要信号算法岗的考察范围正在从“纯数据结构”向“领域算法”扩散。也就是说你把排序和DP背得滚瓜烂熟只是入场券真正决定你能不能进面试的是你对特定业务场景中常用算法的理解深度。所以这套A卷虽然名字上叫“算法”但它不是一个单纯的编程竞赛卷。准备的时候既要把基础算法补扎实还要有意识地积累几个领域的常用算法比如推荐系统里必然要碰的协同过滤、Embedding、粗排精排音视频技术里的重采样、编解码策略端的PID控制、卡尔曼滤波等。这种积累不是让你每个算法都推一遍公式而是至少要知道它们解决什么问题、核心思想是什么、和别的方法比优劣在哪。2. 字符串算法怎么考KMP的next数组是入门不是终点热搜词里那条“在KMP算法中对于模式串pabacaba其next数组next[i]定义为……”特别扎眼因为这就是典型的大厂笔试选择题出题风格给一个具体字符串让你推next数组。看起来是送分题但很多人在这一步就开始丢分原因不是不懂KMP而是对next数组的定义理解得不够精确。2.1 next数组的两种定义和一把心酸泪如果你去翻不同教材会发现next数组有两种主流定义一种表示“当前字符之前的子串中最长相等前后缀的长度”另一种是“当失配时模式串指针应该回退到的位置”。这两种定义在具体数值上会差1很多同学最开始学的时候记混了一换教材就懵。我自己当年第一次笔试就吃过这个亏后来总结出一个记忆方法别去背定义去画匹配过程。拿pabacaba举例。我们手动推一遍最长相等前后缀长度也就是经典教材里的前缀表子串a最长相等前后缀长度是0。子串ab前缀a和实际后缀b不相等长度是0。子串aba前缀a等于后缀a长度为1再看ab不等于ba所以最长是1。子串abac前缀a不等于后缀cab不等于ac长度为0。子串abaca前缀a等于后缀a长度1ab不等于caaba不等于aca所以最长是1。子串abacab前缀a不等于后缀bab等于ab长度2aba不等于cab所以最长是2。子串abacaba前缀a等于后缀a长度1ab等于ba不等于aba等于aba长度3所以最长是3。这样推下来以“最长相等前后缀长度”为定义的next数组就是[0, 0, 1, 0, 1, 2, 3]。如果题目采用“失配时回退位置”的定义一般会在这个基础上整体做偏移所以做题前第一件事是看清题目给的到底是哪个定义。2.2 笔试里KMP的三种考法KMP在笔试里基本不会让你把完整的匹配代码跑通而是通过三种方式考察你对其原理的掌握度。第一种就是上面说的给一个具体模式串让你推next数组。这种题的坑在于对定义的理解以及对“最长相等前后缀”这个概念是否真正掌握。第二种是问你KMP相比朴素匹配的优化点在哪里标准答案是消除了主串指针的回溯让时间复杂度稳定在O(nm)。这里有个很容易写错的点KMP的优化并不是让模式串不回退而是让模式串的指针按照next数组精准回退主串指针只进不退。第三种是给你一段KMP代码让你填缺失的循环条件或next数组更新逻辑。这种题考的是工程实现细节很多人原理明白但代码写不对归根到底是手写太少。2.3 别把KMP当孤立算法它是字符串题的地基我在准备时候有一个很深的体会KMP不是单独背的一个算法模板它背后是“前缀函数”的思想——预处理模式串自身的匹配信息用它来加速后续匹配。这个思想在字符串哈希、自动机、后缀数组里都有一脉相承的逻辑。快手笔试卷子不会只出一道KMP它可能把字符串题和DP结合比如让你计算一个字符串的最小编辑距离也可能把字符串和滑动窗口结合比如求不重复字符的最长子串。所以我的建议是准备字符串算法时把KMP、Boyer-Moore、Rabin-Karp、Trie树、AC自动机串成一条线来学搞清楚它们各自解决什么场景、时间复杂度是多少、核心优化思想是什么。笔试考的不只是一个算法而是你脑子里有没有“字符串算法工具箱”的概念。遇到一道字符串题你能快速判断该用哪个工具这比会默写某个算法的代码重要得多。3. 排序算法那点事能用但要会讲会写还要会选热搜词里“冒泡排序算法c”“堆排序算法”“快速幂算法c”“排序算法”扎堆出现说明排序依然是算法笔试的绝对高频考点。但你有没有发现大厂笔试题里几乎不会直接出“请实现快排”而是把排序包装成各种场景。3.1 从一道经典变形题看排序的重要性剑指Offer和各家题库里有一道常青树题目最小的K个数。快手算法A卷的笔试题目里大概率会有类似影子。最低级的解法是把数组整体排序取前K个时间复杂度O(n log n)。这个解法不能算错但显然不是出题人想看到的。更优的路径有三条第一维护一个大小为K的最大堆遍历一遍数组堆顶就是当前候选最小值中的最大值最后堆里就是最小的K个时间复杂度O(n log K)第二用快速排序的partition思想平均时间复杂度能做到O(n)但需要修改原数组且平均情况分析比较复杂第三数据范围有限时用桶排序或计数排序时间复杂度能到O(n)。一道看似基础的题能把“你是否理解堆这种数据结构”“你是否掌握快排partition的边界处理”“你是否具备分析数据范围并选择最优算法”这三个层次的功力全部测出来。这就是大厂排序题的核心考法不是考你会不会排序而是考你会不会根据场景做选择。3.2 手写快排最容易翻车的三个地方如果你在编程题里决定手写快速排序有几个坑你一定要注意。第一个坑是递归退出的边界条件。我在带人练题的时候发现很多同学写quickSort函数left和right参数对着对着就串了导致无限递归或者数组越界。正确写法是递归前判断left right就返回这个条件错一个符号就是完全不同的结果。第二个坑是partition的轴选择。经典写法选最右边的元素为轴然后从左往右扫把小于轴的交换到左边这种写法简单但存在一个隐患当数组已经有序时每次划分都极度不平衡递归深度变成O(n)最坏时间复杂度退化成O(n²)。笔试中如果你的解法因此超时是很冤枉的。解决办法是随机选轴或者取左中右三数取中后者在工程中更稳定。第三个坑是元素相等的情况。如果数组里大量元素相等简单partition会把相等的元素全部堆积在一侧一样会导致退化。这时候要用三路partition把等于轴的元素单独放中间一段。虽然笔试数据不见得会卡这一点但你在复杂度分析时主动提到这个优化会让面试官觉得你是真懂排序而不只是背了模板。3.3 归并排序、堆排序的隐藏考点归并排序在笔试里最常见的变形是“数组中的逆序对”。这个问题经典的解法就是在归并排序的合并过程中顺带统计逆序对数量。为什么把这两个知识点绑定在一起因为归并排序合并两个有序数组时右半边的元素插到左半边元素前面中间跨过的元素个数就是逆序对数量。理解了这层关系你用归并写逆序对题就不需要死记代码。堆排序的考点则在两个方向一个是TopK问题前面说过的最大堆思路另一个是堆这个数据结构的插入、删除、调整操作。笔试里经常给你一个数组让你画出它建堆之后的样子或者问删除堆顶元素之后如何调整。很多人写堆排序代码的时候脑子里没有“上浮”和“下沉”的清晰区分写出来的调整逻辑四个if套来套去自己都绕晕。我的建议是先画出二叉树结构再在纸上手动跑一遍调整过程跑通两遍之后再写代码思路会顺很多。4. 动态规划与贪心从“我会套模板”到“我能设计状态”动态规划和贪心算法在算法A卷里的比重非常高而且往往是拉开分数差距的核心题目。热搜词里“贪心算法”“剪枝算法”频繁出现也印证了这点。但很多同学学DP的方式有问题他们不是在学DP而是在背“背包九讲”。4.1 动态规划题的核心是状态转移不是背诵笔试里的DP题永远不会和你平时刷的题一模一样它一定会在场景上做包装可能是买卖股票的最佳时机可能是编辑距离可能是正则表达式匹配也可能是机器人走格子。但无论包装成什么样解题链路都一样定义状态 - 找转移方程 - 确定初始值和边界 - 推演答案。关键在于“定义状态”这一步。状态定义得好不好直接决定转移方程写不写得出来。我经常打一个比方状态定义就是给问题定位坐标轴坐标系建得好每个位置都有清晰含义坐标系建得歪后面全在瞎转。以经典的最长递增子序列为例如果你把dp[i]定义为“以第i个元素结尾的最长递增子序列长度”转移方程就是dp[i] max(dp[j] 1)其中j i且nums[j] nums[i]非常自然。但如果你把dp[i]定义成“前i个元素中最长递增子序列的长度”转移起来反而绕因为你不知道之前子序列最后一个元素是谁没法判断能不能接上。4.2 贪心算法什么时候敢用什么时候别用贪心算法是笔试里最让人纠结的题型。它的代码往往很短短到你会怀疑答案是不是太简单了。但判断一道题能不能用贪心需要严谨的论证而不是靠感觉。我的经验是笔试中能用贪心解决的题目通常有一个明显的信号局部最优选择会在每一步推进时逐步累积成全局最优而且没有后效性。什么叫没有后效性拿经典的“跳跃游戏”来说你在第i个位置能跳到的最远距离只取决于当前位置的覆盖范围不会因为之前选择跳到了这里而改变。这种问题就可以放心贪心。但像“0-1背包”这类问题你在这个物品上选了装或不装会直接影响后续容量就不能贪心必须DP。很多同学栽跟头的点就在这里遇到一道题感觉贪心能解直接写了一版样例能过交上去超时或答案错误回头看才发现贪心局部最优推不出全局最优。如果你想彻底搞清楚一道题能不能贪心可以在练习时多问自己一个问题“如果我这一步选了看似最优的方案会不会导致后面失去一个更优的选择”如果会基本不能用贪心如果不会贪心大概率可行。这个思维习惯一旦养成远比多刷几十道题有用。4.3 剪枝算法的本质搜索优化也是算法基本功热搜词里“剪枝算法”单独出现但笔试很少直接考剪枝概念而是把它藏在搜索题里。比如N皇后问题、数独求解、子集枚举这些题本质是DFS回溯数据规模一大就要剪枝。快手算法A卷里的压轴编程题有时会落到这种类型上。剪枝的核心思想一句话就能概括在搜索树中如果某个分支已经能判断出不可能产生更优解就提前停止搜索。具体手段包括可行性剪枝、最优性剪枝、记忆化搜索。我建议准备的时候把“回溯 剪枝”当做一个整体来练从全排列问题入手理解状态重置再过渡到N皇后和数独。这类题写对不容易但一旦你把搜索树在脑子里画出来了很多题目会豁然开朗。5. 图论与数值算法A卷里的“领域题”怎么准备前面几部分讲的是通用算法地基但快手算法A卷不是单纯的通用算法考试。从热搜词可以看出音视频重采样、PID控制、卡尔曼滤波、粒子群算法这些领域算法也频繁出现在大家的搜索记录里。这说明快手的算法团队在招人时对不同方向的候选人会有针对性的考察。5.1 最短路、最小生成树、拓扑排序图论是通用硬通货由于快手整个推荐系统、内容分发网络、用户关系链背后都是大规模图结构图论算法在笔试试卷里的出场率相当稳定。常规考点包括Dijkstra最短路、Floyd多源最短路、Prim和Kruskal最小生成树、拓扑排序判断有向图是否有环、二分图匹配等。准备这一块我的建议是把每个算法的适用条件和复杂度烂熟于心。比如Dijkstra不能处理负权边Floyd适合稠密图的任意两点最短路Kruskal靠并查集实现且适合边稀疏的图Prim适合点少边多的图。这些特性不是死记硬背而是要理解它们各自的实现原理后自然记住。笔试题喜欢这么出给你一个场景问应该用哪种算法。你要是只记得算法代码但不知道适用条件这种题就直接送掉了。5.2 粒子群、卡尔曼滤波、PID这些“热搜算法”怎么准备算法A卷会不会直接考粒子群算法说实话直接考的概率很低但作为选项出现在选择题里是完全可能的比如让你判断“粒子群算法属于哪一类优化算法”答案应该是群体智能优化算法。或者问你“卡尔曼滤波的核心思想是什么”你要能答出“预测 更新”这两个交替进行的步骤。准备这类领域算法不要过度恐慌也不要完全忽略。我当时的策略是列出十几个高频领域算法每个算法用一张卡片记五要素解决什么问题、核心思想是什么、输入输出是什么、和同类算法比优缺点在哪、有没有经典应用场景。这样记下来的东西应付选择题和简答题绰绰有余而且这些积累在面试环节的价值远大于笔试。音频重采样算法、BM25、图像锐化拉普拉斯算法这类题目一般出现在与具体方向匹配的笔试试卷里。如果你是投递音视频算法岗那重采样、FFT、编解码这些要重点准备如果是推荐算法岗BM25可以作为文本匹配基础了解一下如果是图像方向拉普拉斯算子属于图像锐化的基础卷积核。方向匹配比大而全更重要。5.3 概率统计与机器学习基础题别被“纯算法”迷惑除了标准算法题算法A卷里通常还有概率统计和机器学习的基础题。常见的有贝叶斯公式计算后验概率、朴素贝叶斯的独立性假设、过拟合的解决办法、精确率与召回率的区别、AUC曲线怎么理解。这一块很多科班同学反而不太重视觉得笔试嘛代码写出来不就行了。但现实是算法岗位的笔试选择题里机器学习基础题往往占比不低。而且这些题拿分相对容易属于“背了就能拿分”的部分性价比极高。我在刷题后期把李航老师的《统计学习方法》前几章配合面经里出现过的选择题过了两遍效果非常明显。6. 笔试里的隐藏坑时间复杂度和边界条件是怎么吃掉你的分的这部分是我最想重点说的因为太多同学明明算法思路正确代码也写得出来但最后分数就是上不去。问题往往不在算法本身而在那些你觉得自己没问题的细节上。6.1 数据范围里藏着的玄机笔试编程题不会直接把“请用O(n log n)算法”写在题目里它通过数据范围来暗示你。如果n 100O(n³)的Floyd可以大胆用如果n 10⁵O(n²)的暴力基本就不可能过了最少也要O(n log n)如果n 10⁹那你连O(n)都要掂量一下基本得靠数学公式或矩阵快速幂了。我在批改别人代码的时候见过太多次这样的惨案一道题给n到10⁵循环里套循环测试样例全过一提交超时。笔试题的测试数据分布往往在小规模和大规模两个极端都有覆盖你在大数据下超时就是整道题判错。所以拿到题先看一眼数据范围马上估算一下自己解法的时间复杂度是否可行这应该成为肌肉记忆。6.2 边界条件不是无聊的细节很多同学代码写完之后满脑子都是主逻辑测试样例一过就舒一口气直接交卷。但算法笔试最先跑的就是各种极端情况空数组、只有一个元素、所有元素相等、目标值不存在、数组越界。边界条件这类问题在编程题里非常致命因为判题系统不会告诉你错在哪个测试点。我给你一个我坚持了很多年的习惯写代码前先在注释里写清楚边界条件写完后一步步手动走一遍伪代码涵盖最小值、空值、重复值。虽然看上去麻烦但真的能救回严重的分数损失。6.3 int溢出这种低级错误大厂笔试的数据范围经常会给到10⁹甚至更大两个int一乘直接溢出结果就是整道题答案错误。避免的办法很简单看到涉及加法乘法的计算尤其是累加、阶乘、组合数立刻设long long。虽然这看起来是低级问题但越是紧张越容易犯我建议在刷题阶段就养成无脑long long的习惯把风险直接掐死在摇篮里。另外还有一个很少被提起的坑Java中的Arrays.sort在极端情况下可能会触发TimSort的比较器一致性检查如果你在比较器里返回的结果不满足自反性、对称性、传递性会直接抛异常。这个坑在LeetCode上出现过笔试现场一旦踩中排查起来相当费时间。7. 从快手A卷反推出来的备考节奏三个月我这样安排现在秋招节奏越来越早很多人六七月份就开始投提前批了。如果你的目标是算法岗大厂offer留出三个月做系统性准备是比较稳妥的。我根据自己的实战经验和带人的经历给你一个可执行的节奏参考。7.1 第一个月基础算法地毯式复习第一个月的任务不是刷题而是建立完整的知识体系。数据结构上数组、链表、栈、队列、哈希表、树、堆、图这些都要过一遍知道每个数据结构的操作复杂度。算法上排序、二分、双指针、滑动窗口、DFS、BFS、回溯、贪心、DP、图论最短路、最小生成树逐个吃透。这一阶段最忌讳眼高手低。你看懂了KMP原理和你能手写出无bug的KMP是两码事。我建议每个算法都从最朴素的版本写起然后尝试优化最后默写一遍。写完之后对照标准答案看边界条件处理有没有遗漏。这个过程比较折磨人但基础扎实与否三个月后你会在考场上真切感受到差距。7.2 第二个月按专题刷题加总结有了基础框架之后第二个月开始按专题刷题。每天给自己定一个专题方向比如今天全做字符串题明天全做DP题。刷题量不在多一天三到五道完全足够但要求每一道都复盘。复盘怎么写我自己的模板是这样这道题考察的核心知识点是什么我的第一思路是什么最优解的关键一步是什么我卡在哪个细节上如果换个数据范围我还敢用这个方法吗这样一条条写下来一周之后你就能发现自己哪类题目最容易卡壳然后再针对性强化。相反如果只刷题不复盘刷一百道效果也有限。7.3 第三个月真题模拟和心态管理第三个月进入冲刺阶段这时候不要再盲目刷题了要做整套模拟。找几套历年大厂算法笔试题或者LeetCode周赛题给自己设置一个和正式笔试一样的时间比如90分钟到点就停然后客观评分。模拟的目的有两个一是练时间分配很多同学在一道题上死磕太久导致后面简单的题都来不及写二是练心态很多同学平时刷题很顺一上考试环境就紧张大脑一片空白。提前适应这种紧张感很有用。到考前一到两周我建议把之前整理过的算法复杂度表、边界条件checklist、领域算法卡片拿出来反复看不再接触新题。这个时候再学新东西只会增加焦虑不如把手头已有的知识稳稳拿住。考试的时候遇到没思路的题先跳过把能拿的分全部拿到再回头啃硬骨头。如果你能把这一套流程走下来快手算法A卷这种级别的笔试大概率不会成为你的拦路虎。退一步说即使某一套卷子发挥不佳这套方法论和知识体系也不会浪费因为接下来你还要面对更多大厂的笔试每一场都是对你算法功底的校验。把每一次笔试当成一次修行踩过的坑、写过的代码最后都会变成你手里实实在在的筹码。