快手这家公司从短视频到直播再到后来的电商和本地生活技术体系的复杂度是逐年攀升的。正因如此它家的校招笔试题目一向在“工程落地”和“基础功底”之间找平衡。2019年秋季那场校园招聘笔试的工程B试卷虽然过去几年了但回过头来看里面的出题思路、考察重点跟现在大厂的工程岗笔试套路几乎一脉相承甚至可以说是很多后来者的“模板”。我当时认真刷过这套卷子也陪着几届学弟学妹复盘过今天就把这套工程B试卷的考察逻辑、核心考点和现场答题策略掰开揉碎讲清楚。这套卷子适合谁看如果你是正在准备大厂校招的应届生尤其是后端、基础架构、客户端方向的工程岗那这份复盘能帮你少走不少弯路。如果你只是对大厂笔试好奇想看看他们到底筛选什么样的人这篇文章也能给你一个比较直观的参考。我会从试卷结构、算法题、计算机基础、语言特性、系统设计、智力题这几个维度逐一拆解中间穿插一些我自己刷题和面试时的真实体会。1. 工程B试卷的整体面貌与出题逻辑很多人拿到这套卷子第一反应是“题量怎么这么大”。其实快手这类互联网公司的校招笔试从来不是让你把每道题都做完而是在有限时间内考察你的“优先级判断力”和“抗压能力”。工程B试卷整体分成了几大块包括客观选择题、手写编程题、系统设计题以及一部分逻辑智力题。考试时间一般卡在90到120分钟题量通常在10道选择、2到3道编程、1道设计题左右外加几道小题。1.1 题目结构与时间分配建议从结构上看选择题覆盖的知识面非常广包括数据结构、操作系统、计算机网络、数据库、Java或C语言特性甚至还有一些概率论的基础题。这部分是“快问快答”类型平均每道题不能超过2分钟。有些题就是纯粹考察概念比如TCP三次握手的状态变化或者HashMap在JDK 7和JDK 8之间的区别这些背过就有分但没复习过就真的只能靠蒙。接下来是编程题这部分通常是2到3道算法题难度从LeetCode中等偏易到中等偏难不等偶尔会有一道压轴的偏难动态规划。快手工程B试卷的编程题一般不会出那种纯数学推导的偏题怪题更多是考察你“能不能把常见的数据结构用熟”。比如树的遍历、图的最短路径、贪心、双指针、前缀和之类的都是高频区间。系统设计题则非常有意思通常会给一个具体的业务场景比如“设计一个短链接服务”或者“设计一个关注列表的推送系统”让你用一两页纸去描述方案。这道题不要求你写出完整代码但对你的架构思维、技术选型和边界考虑要求很高。很多第一次参加笔试的同学会在这道题上严重翻车因为平时的刷题训练根本覆盖不到这个维度。1.2 为什么快手会这么出题快手当时的业务增长很快用户量巨大加上视频和直播的场景极其依赖推拉流、上传下载、实时互动所以他们对工程同学的要求很明确基础必须扎实在分布式环境里能处理问题同时能写一手干净的代码。工程B试卷的“B”大概率对应的是后端或者基础工程方向所以考察内容会更偏服务器、存储和中间件这些领域。这套卷子筛的不是“你背了多少面试题”而是“你有没有形成计算机的底层知识框架”。你会发现选择题里很多题目是在交叉考察比如操作系统里的页面置换算法会结合到设计缓存时的淘汰策略网络里的拥塞控制会跟分布式系统中的流量控制结合起来。如果只是死记硬背很难拿到高分。2. 算法与数据结构笔试的主战场算法题永远是笔试中最拉分的部分工程B试卷也不例外。快手这类公司面试官阅卷时对算法代码的评判标准通常不是单纯看“对不对”而是看“复杂度是否达标”和“代码风格是否成熟”。同样一道题暴力解法可能AC不了最后一个大数据用例但优化解能全过。2.1 高频题型的考察思路从这套卷子反映出的出题倾向来看有几种题型几乎年年出现。第一种是“数组与哈希表”的组合题比如“给出一个数组找出和为target的两个数下标”。这种题看起来简单但快手通常会在边界条件上埋坑比如数组可能包含负数比如要求返回下标的字典序最小组合。第二种是“二叉树相关问题”比如最近公共祖先LCA、层序遍历、路径求和。树的题考察的是递归和迭代两种写法如果你只会递归遇到深度极端的用例可能爆栈。第三种是“贪心与动态规划”这是区分度最大的一块。工程B卷压轴算法题往往是一道中等偏上的DP比如“编辑距离”“最长上升子序列”“打家劫舍变种”等。这类题光知道状态定义还不够还要能准确推导转移方程并考虑状态压缩的空间优化。很多同学能在十分钟内看出是DP题但状态定义一错后面全崩。第四种是“图论基础题”比如拓扑排序、并查集判断连通分量、Dijkstra最短路。这里要特别提醒快手笔试的ACM模式跟LeetCode的核心代码模式不一样输入输出需要自己处理。很多同学在ACM模式下会紧张明明思路对结果卡在读取输入或者格式化输出上。2.2 从暴力到最优的答题策略我在实际操作中有一个经验拿到算法题如果5分钟内没有清晰思路先写一个暴力解保底哪怕只能过一部分用例也能拿到部分分数。笔试判卷通常是按通过用例比例给分不是零一制。写完暴力解后再回头优化不要一开始就死磕最优解导致最后时间耗尽一道题都没交。以一道典型的“最大连续子数组和”为例暴力解是三层循环枚举起点、终点并求和复杂度O(n^3)这种代码用来保底但肯定超时。然后可以用前缀和优化到O(n^2)用数组sum[i]表示前i个元素的和子数组和直接用sum[j]-sum[i]得到。最后的最优解是Kadane算法也就是动态规划的一维版本维护一个cur变量表示以当前元素为结尾的子数组最大和cur max(cur nums[i], nums[i])同时用global_max记录全局最大。这道题之所以高频是因为它从暴力到动态规划的进化路径非常清晰可以考察候选人的思维梯度。2.3 一个典型题目的现场推导我拿一道类似工程B卷风格的题目示例一下推导过程。题目是“给定两个有序数组找出合并后的中位数”要求时间复杂度O(log(mn))。这道题如果直接合并两个数组复杂度O(mn)不算错但O(log(mn))的要求直接指向二分法。核心思路是对较短的数组二分划分位置通过中位数的性质确定另一个数组的划分位置使得左右两部分元素个数相等且左边最大值小于右边最小值。这里最大的坑是边界条件比如某一个数组完全在左边或右边需要设置哨兵值去处理。写代码时我会习惯性地加上注释说明每个边界判断的含义这样阅卷人一眼就能看出你懂原理。笔试阅卷还有一个隐形的加分项变量命名清晰函数拆分合理。如果所有逻辑都堆在main函数里变量名都是a,b,c,d即使算法对了印象分也会打折扣。反过来代码结构清爽有合理的函数划分容易让阅卷人对你的工程能力产生信任。3. 计算机网络、操作系统与数据库工程基本功工程B卷的选择题和简答题里计算机基础占了很大比重。这部分不能靠临时抱佛脚必须形成体系。我见过太多同学算法题做得飞起但一问TCP和UDP的区别只能说“TCP可靠、UDP不可靠”这种颗粒度远远不够。3.1 计算机网络怎么复习才够用网络部分工程B卷反复出现在这几个知识点上TCP三次握手与四次挥手的状态变迁、TCP的拥塞控制慢启动、拥塞避免、快重传、快恢复、HTTP与HTTPS的差异、DNS解析过程、TCP粘包问题、HTTP/2的多路复用等。其中TCP状态变迁几乎是必考比如你知道TIME_WAIT出现在主动关闭方还是被动关闭方答案是主动关闭方在收到对端的FIN后进入TIME_WAIT状态持续2MSL以确保最后的ACK可达并让旧连接中的报文自然消失。2MSL的时长一般在1到4分钟之间具体看系统实现。HTTP与HTTPS的差异不能只从“加密”两个字回答要能把握手流程讲清楚。HTTPS额外使用了TLS协议握手时先做证书校验再交换密钥后续通过对称加密传输数据。这里还有一个高频追问HTTPS一定安全吗答案是否定的如果客户端没有校验证书或者被安装了恶意根证书中间人攻击依然可能成功。所以考核这个知识点本质上是在考察你是否真正理解“安全是分层的”。UDP在快手这类流媒体公司里地位很高因为视频直播场景大量使用UDP或者基于UDP的QUIC协议。这里问一个深的TCP的粘包和拆包是怎么回事原因是TCP是字节流协议没有消息边界应用层需要自己定义消息格式常见的解法是定长消息、分隔符、或者长度字段前缀。推荐的做法是长度字段前缀比如4字节的int表示消息体长度这也是很多RPC框架的做法。3.2 操作系统的一些高频考点操作系统里的高频考点主要集中在进程与线程的区别、死锁的四个必要条件、虚拟内存与页面置换算法、进程通信方式。这些概念要能说出“What”“Why”“How”三层。比如死锁光知道四个必要条件互斥、持有并等待、不可剥夺、循环等待是不够的要能解决实际问题。笔试经常会出这样的题银行家算法里给定可用资源向量和每个进程的已分配资源与需求资源判断系统是否处于安全状态。解这种题要按顺序模拟选择满足需求且能释放资源的进程执行直到所有进程都能完成。如果找不到这样的进程就说明不安全可能死锁。虚拟内存的面试题则会更贴近实际为什么需要虚拟内存核心原因是让多个进程可以共享物理内存同时提供隔离和扩展。页面置换算法里LRU是考察重点但工程实现一般不会用时间戳而是用双向链表加哈希表保证O(1)复杂度。这个思想对应到算法题就是LeetCode的LRU Cache工程B卷的算法题如果考这个务必提前练熟。进程通信方式也是高频区管道、消息队列、共享内存、信号量、Socket各有适用场景。笔试有时会问“为什么共享内存效率最高”答案是因为不需要内核拷贝数据但需要同步机制保护。这个问题一旦展开就又回到了并发控制上可见这些基础都是串联的。3.3 数据库一线工程师必须懂的索引与事务数据库题的出题思路通常非常“业务化”围绕索引失效、事务隔离级别、悲观锁与乐观锁、SQL书写与优化展开。作为工程岗数据库是躲不开的存储基础所以这部分得分率往往能反映真实水平。索引那一块必考B树为什么适合做数据库索引。你至少要说清楚三点树矮、磁盘IO次数少叶子节点形成有序链表适合范围查询所有数据都在叶子节点查询性能稳定。还要知道聚簇索引和非聚簇索引的区别InnoDB的聚簇索引就是主键索引叶子节点存放整行数据非聚簇索引的叶子节点存放主键值因此查询非索引字段的时候需要回表。索引失效的场景在选择题里出现概率极高。常见的判断规则有最左前缀原则、在索引列上做函数操作会导致失效、隐式类型转换会导致失效、用不等于或者like左模糊会导致失效。我记得有一道题是这样设计的给一个联合索引(a,b,c)问下面几个查询里哪些能命中索引。只要记住最左前缀再加上“遇到范围查询后面的列会失效”基本就能答稳。事务方面ACID四个特性要能解释清楚尤其是隔离性如何通过锁和MVCC实现。四个隔离级别的脏读、不可重复读、幻读问题要一一对应。这里有个容易混淆的点可重复读级别在MySQL的InnoDB下是否能解决幻读答案是大部分情况能因为Next-Key Lock锁住了范围但在某些特殊场景下仍可能出现幻读。面试官如果追问到这个深度已经不只是笔试的范畴了。4. 语言特性与手写代码工程感的直接体现工程B试卷一般会让你选择熟悉的语言Java、C、Python、Go都可以但每个语言背后的运行机制考察深度完全不同。快手后端早期以Java为主所以Java方向的题目相对更多但C和Python的题也不少见。4.1 Java方向的高频考点对于Java方向HashMap几乎年年上榜。要掌握的点包括JDK 7和JDK 8在数据结构上的差异数组加链表 vs 数组加链表加红黑树、扩容机制默认容量16负载因子0.75扩容为原来的2倍、put方法的大致流程、为什么链表长度超过8会转红黑树为了抵消哈希碰撞恶化时的性能损失。还要知道HashMap不是线程安全的多线程扩容时JDK 7版本可能形成环形链表导致死循环JDK 8虽然修了这个问题但并发下仍然可能丢失数据所以并发场景要用ConcurrentHashMap。JVM内存结构也是重点。堆、虚拟机栈、本地方法栈、方法区元空间、程序计数器每一块存什么、会抛出什么异常都要清楚。笔试喜欢设陷阱的题目是判断一个对象是否“死亡”用的是可达性分析而不是引用计数法因为循环引用问题在引用计数下无法解决。G1垃圾回收器在JDK 9之后成为默认垃圾回收器它的Region划分、可预测停顿、并发标记等都是加分项。线程池的一堆参数也是从笔试到面试的多发区。核心线程数、最大线程数、非核心线程存活时间、任务队列类型、拒绝策略为什么线程池不允许用Executors.newFixedThreadPool因为默认的任务队列是无界LinkedBlockingQueue极端情况下会堆积大量请求导致OOM。规范的做法是用ThreadPoolExecutor手动创建指定有界队列和合理的拒绝策略。4.2 C与Python方向的常见考点如果你选择C虚函数表、智能指针、STL容器复杂度、std::move和完美转发这些话题是绕不开的。智能指针里shared_ptr的引用计数是不是线程安全的答案是引用计数本身是原子的但指向的对象不是所以多线程读写同一个shared_ptr保护的对象时依然要加锁。C的题往往会多一些内存细节的考察比如struct的对齐规则。Python方向则更关注GIL、list与dict的时间复杂度、装饰器、生成器、深拷贝与浅拷贝。GIL的问题尤其容易出成简答题多线程爬虫在Python里是不是一定能加速答案是在CPU密集任务下并不能因为GIL同一时刻只允许一个线程执行Python字节码真正的并行需要多进程。但在IO密集任务下多线程因为释放GIL依然有优势。4.3 手写代码题的现场得分技巧笔试手写代码不是写出来就完了还要注意可读性和鲁棒性。我的一个习惯是写之前先在草稿纸上把边界条件列出来比如链表为空、数组只有一个元素、整数溢出等然后再动笔写正式代码。另一个习惯是写完代码后自己跑一遍边界用例在注释里标注一下输出能明显减少低级Bug。快手工程B卷的手写代码题出现过类似“复制带随机指针的链表”“判断一棵树是否是二叉搜索树”这类题目。这些题最优解虽然不难但边界细节很多。以复制随机指针链表为例最优解一般是在原链表每个节点后面复制一个新节点然后重新设置random指针最后拆分链表。写代码时拆分那一步特别容易写错务必要用prev指针维护前一节点。5. 系统设计与场景题拉开层次的关键很多同学看到系统设计题就懵实际这恰好是工程B卷里最有意思的部分。因为这道题没有标准答案但可以通过你的回答看出你是否有完整的架构思维和工程判断力。5.1 一个经典设计题的答题框架工程B卷曾出现过的系统设计题目我印象比较深的是“设计一个短链接系统”。这道题看似简单实际上可以从多个维度衡量候选人。我是按照下面这个框架来作答的首先是需求分析明确核心功能是把长链接生成短链接以及短链接跳转到长链接。接着要估算QPS和数据量如果公司每天有100万条新链接生成短链接的跳转量可能是生成量的100倍也就是1亿次每天折算下来约1160 QPS峰值可能是这个的3到5倍。数据存储上如果把短码设为7位62进制可容纳62^7个组合大约是3.5万亿完全够用。生成短码的方案有很多我会优先提发号器方案用数据库自增ID或者Snowflake算法生成全局唯一ID再把ID转成62进制字符串。为什么不用随机MD5截断因为可能出现碰撞需要重试且无法保证短码有序。发号器方案的另一个好处是短码有趋势递增性有利于数据库索引优化同时方便做分库分表扩展。跳转的存储层可以设计成一张短码到长链接的映射表读多写少所以可以加一层Redis缓存缓存未命中再查MySQL同时通过布隆过滤器拦截不存在的短码防止缓存穿透。整个架构画下来再补充分布式ID的高可用、缓存淘汰策略、过期链接清理方案这道题基本上就稳了。5.2 场景题如何体现工程思维场景题考察的核心不只是你会多少技术而是你的“工程折中”意识。比如设计一个关注列表推送系统有人上来就写Kafka、Flink、推拉结合但如果不解释为什么“大V粉丝多需要拉模式普通用户粉丝少用推模式”那方案就只是名词堆砌。我认为比较好的作答方式是先给问题分层再对每一层说明权衡。第一层是数据模型关注关系如何存储是A关注B还是B被A关注如何用MySQL存大规模关系。第二层是推送时机是用户发视频时触发还是定时扫描还是粉丝拉取时实时计算。第三层是实时性要求比如快手这种视频App用户希望看到关注的人最新动态所以延迟控制在秒级。最后是容量规划结合用户量、关注关系数量等估算存储和带宽。这种逐层拆解的习惯本质上就是一种工程思维。笔试时即使时间不够把每一层写上一两句也比整页只画一个框强得多。6. 智力题与综合素质别在阴沟里翻船工程B试卷里偶尔出现的智力题本质上是考察逻辑推理和数学敏感度。这类题不需要特别准备但只要掌握几个常见模型就能稳定得分。6.1 概率题的常见模型比如“一个家庭有两个孩子已知其中一个是女孩求另一个也是女孩的概率”。很多人脱口而出1/2正确答案其实是1/3因为样本空间是男男、男女、女男、女女已知一个是女孩排除男男剩下三个等可能女女只占一个。这种题考察的是条件概率的基本概念如果这个都不稳说明概率论基础还需要补。再比如“100层楼两个鸡蛋问题”这是经典动态规划题笔试有时会以选择题形式考到。核心思路是设置一个最大尝试次数k第一次从第k层扔第二次从第2k-1层扔依次递减使得总次数不超过k。解不等式k(k1)/2 100得到k的最小值是14这是最优解。能把推导过程写出来比直接背答案更有说服力。6.2 时间分配与心态管理笔试题量大时间紧最重要的一步就是“学会策略性放弃”。我的建议是优先做你熟悉的题型先把该拿的分拿到再去啃硬骨头。如果一道题卡了10分钟果断跳过最后有剩余时间再回头推。笔试是排位赛不是满分赛你做不出来的题绝大多数人同样做不出来但如果你因为一道题浪费太久导致后面全崩那就完全得不偿失了。另外注意选择题的“单选”和“多选”提示。工程B卷这类试卷经常出现“多选”题少选通常不得分或者得部分分所以拿不准的选项不要乱选。我在实际监考中见过太多同学明明知道正确选项却被错误的干扰项迷惑多选了一个答案整题零分非常可惜。7. 实用备考建议与心态调整笔试考的不只是知识储备还有临场状态和策略。经历过秋招的人都知道那一两个月是“身体和心态的双重消耗战”尤其是工程B卷这种综合性强的试卷提前做好规划很重要。备考方面我建议按“算法 基础 项目”三条线并行复习。算法线每天保持1到2道LeetCode重点刷数组、链表、树、动态规划和图论基础线每周安排固定时间看《计算机网络》《操作系统》的重点章节可以用思维导图做总结项目线要把自己简历里的项目吃透能画出系统架构图能说出每一项技术选型的理由。笔试只是第一关之后的面试一定会深挖项目。还有一点做题之后一定要复盘。我会把错题按知识点分类整理成自己的“错题本”每周过一遍。其实大厂的考点就那么几百个你吃透一个就少一个盲区这套工程B卷的很多选择题如果你做过其他大厂的真题会发现考点是高度重合的。在实际操作中我还发现一个容易被忽视的点笔试环境。很多笔试用的是牛客网或者赛码网代码编辑器没有自动补全缩进可能也有问题如果你平时在IDE里写代码习惯了突然换到这种环境会非常不习惯。所以考前一定要去牛客网刷几套模拟卷熟悉ACM模式的代码输入输出适应限时环境练习使用日志输出调试。这个准备往往比多背几道面试题更值钱。最后再说一个跟考题无关但很关键的事情时间安排。秋招笔试通常集中在晚上或周末如果你白天还有实习晚上状态可能会很差。我的经验是提前一周调整作息考试当天少喝咖啡确保大脑供血充足。这种细节说起来简单但对答题稳定性影响很大。快手2019年秋季那套工程B试卷放到今天看依然是一套结构非常典型的工程校招笔试题。它的价值不在于让你背下具体某道题的答案而是帮你建立一套应对大厂笔试的方法论基础扎实、算法熟练、设计有逻辑、考试有节奏。希望对正在准备笔试的同学有实质性的帮助。