ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

快手校招工程A笔试解析:后端岗考点、题型与备考路线

快手校招工程A笔试解析:后端岗考点、题型与备考路线 快手2020校园招聘秋招笔试——工程A试卷这个名字在当年的校招圈里不算陌生。它是快手面向后端研发类岗位设置的笔试卷和算法岗、客户端岗分开命题重点考察候选人的编程功底、工程实现能力和系统设计意识。如果你正在准备互联网公司的后端岗不管目标是不是快手这套卷子的题型思路和考点分布都有很强的参考价值。我结合自己做题时的经历和后来参与校招命题的一些体会把这类工程卷的考察逻辑、核心考点、典型题目和备考路线完整拆一遍。1. 快手“工程A”这份卷子到底在考什么快手2020届秋招大约是在2019年下半年走的线上笔试流程整套流程和当时多数大厂保持同一节奏。很多同学第一次看到“工程A”这个名字都会愣一下搞不清它跟算法卷、测试卷有什么区别。按我当时了解的情况这份卷子主要面向后端研发方向的候选人考察目标非常明确能不能写稳代码能不能理解系统运行的基本原理有没有基本的工程素养。1.1 为什么单独给“工程”出一套卷后来我参与过几次校招笔试命题才真正理解这个分类背后的逻辑。命题组最怕的其实不是候选人不会写代码而是候选人只会写“题解”不会写“工程”。有人可以在竞赛题上拿高分但一问到线上接口超时怎么办、数据库索引怎么建、缓存和数据库一致性怎么保证就完全没有头绪。这种候选人刷题刷得很猛但离真实业务很远。所以快手这类公司在后端岗位单独出工程卷本质上是把考察重心从“算法竞技”拉回到“工程实现”。工程A试卷的命题风格有几个明显特点第一不追求偏题怪题核心考点基本都是计算机基础里最常用、最该掌握的东西第二编程题难度有梯度第一题通常温和保证大多数人能拿基础分后面逐步加深用区分度拉开档次第三会有一道开放性设计题没有标准答案考察的是分析思路和方案完整性而不是单纯背知识点。1.2 工程A的题型分布与考察目标从当年参与笔试的同学在论坛上的反馈和博客里的零散回忆来看工程A卷大致由三部分组成选择题单选加多选、编程题、问答题或设计题。原题到现在肯定没法完整复原但这类试卷的题型比例在大厂校招里高度一致可以整理成下面这个参考表题目类型预计题量分值占比考察方向选择题15到20道20%到30%计算机基础、语言特性编程题2到3道40%到50%数据结构、算法、编码能力设计题1道20%到30%系统设计、方案表达选择题覆盖范围非常广操作系统、计算机网络、数据库、Java或C语言基础都可能出现个别题还会涉及Linux常用命令和git操作。编程题以medium难度为主偶尔有hard但不会出需要冷门数学结论的题。设计题则非常贴近业务场景比如让你设计短链接系统、设计一个排行榜、设计一个关注关系存储方案。提示这里说的“工程A”默认指服务端或后端方向。客户端、前端方向会有对应的工程B、工程C侧重点不一样但整体准备思路是通用的。概括来说这份卷子想筛选的人是基础理论扎实、代码写得干净、遇到开放问题能结构化思考。这三个能力不是考前突击能补出来的需要平时的长期积累。2. 核心考点拆解从理论到代码这一节我把工程A卷里最高频的考点按模块拆开讲。每一块我都会说清楚“考什么”“为什么考”“怎么复习”这样你在复习的时候优先级会更清楚。2.1 数据结构与算法笔试的“硬通货”编程题基本绕不开这几个数据结构数组、链表、栈、队列、哈希表、二叉树、堆。其中链表和二叉树是很多题的基础载体哈希表是用来优化时间复杂度的常见手段堆则频繁出现在TopK、中位数、任务调度这类场景里。LeetCode上题目做多了会发现笔试考来考去就是这些模型的组合变形。具体到题型我认为最高频的几类是TopK问题比如找数组第K大、求流中位数常考堆和快速选择。链表操作反转链表、合并有序链表、判断是否有环这些属于基本功中的基本功。二叉树遍历前中后序、层序遍历以及由遍历序列重建二叉树。动态规划背包、子序列、编辑距离这类题最考验状态定义能力。缓存算法LRU、LFU这类以“实现一个缓存”为载体的综合题考数据结构的组合使用。这里有一个容易被忽略的点笔试用的是ACM模式还是核心代码模式直接影响答题策略。有些平台只需要你补全函数体有些平台要求自己处理输入输出。我强烈建议备考阶段就习惯写完整代码不要只写函数体因为真到笔试现场输入输出处理出错会白白丢分。2.2 操作系统与网络必须拿分的基础题选择题里操作系统和网络是重头戏而且这些题的难度远低于考研那种深度偏重概念理解和简单计算。操作系统的高频考点包括进程和线程的区别、死锁的四个必要条件、进程间通信方式、虚拟内存与页面置换算法、共享内存和消息队列的对比。网络方面TCP三次握手和四次挥手基本必考TCP和UDP的区别、HTTP状态码的含义、HTTPS建立连接的过程、滑动窗口和拥塞控制这些都属于需要能默写的级别。这类题为什么值得重视因为它们的区分度不高属于“背了就有分”的部分。很多人把精力全放在编程题上结果选择题错一堆最后总分反而上不去。我的建议是考前一到两周把操作系统和网络的高频概念整理成一份速查表每天花半小时过一遍比临时刷十道算法题性价比高。2.3 数据库与分布式基础工程卷的隐藏重点工程卷跟算法卷最大的不同就是会把数据库和分布式内容放进选择题甚至设计题里。数据库最常考的一个是索引比如B树为什么适合做索引、联合索引的最左前缀原则、索引失效的典型场景另一个是事务ACID特性、隔离级别、MVCC机制、乐观锁和悲观锁的区别。分布式基础方面常见考点包括CAP理论怎么理解、负载均衡有哪些策略、缓存穿透和缓存雪崩分别怎么解决、消息队列解决什么问题、分布式唯一ID的生成方式有哪些。这些内容可能不会单独出大题但在设计题里一定会用到。比如让你设计一个秒杀系统你得能讲清楚怎么用Redis缓存商品库存、怎么用消息队列削峰、怎么处理超卖问题这背后全是分布式基础。复习这块内容不要照抄八股文要结合场景去理解。比如“缓存穿透”这个问题你自己动手画一下请求流程图理解为什么缓存里查不到、数据库也没数据、每个请求都打到数据库自然就记住了解决方案。我遇到过很多候选人能背出“布隆过滤器”几个字但问他在什么场景下才需要引入布隆过滤器就说不清楚了。这种“知其然不知其所以然”的状态在笔试设计题里很容易露馅。3. 真题风格模拟三道典型题目实战这一节我挑三道很有代表性的题目按工程A试卷的风格模拟一遍。三道题分别对应基础编码、经典算法、系统设计三个层次也是笔试中最常见的三种形态。3.1 编程题带过期时间的LRU缓存第一道编程题很可能是一个综合性的数据结构实现比如“实现一个带过期时间的LRU缓存”。这道题考察的要点很多双向链表和哈希表的组合使用、过期时间的删除策略、并发环境下的安全性。先说基础版本设计思路是哈希表负责O(1)查找双向链表负责O(1)插入和删除。每次访问或插入时把节点移到链表头部超过容量时删除链表尾部节点。我用Python写一个精简实现import time class LRUCache: def __init__(self, capacity: int, ttl: int 0): self.capacity capacity self.ttl ttl self.cache {} self.rec {} def _is_expired(self, key): if self.ttl 0: return False return time.time() - self.rec[key] self.ttl def get(self, key: int) - int: if key not in self.cache: return -1 if self._is_expired(key): self.cache.pop(key) self.rec.pop(key) return -1 val self.cache.pop(key) rec self.rec.pop(key) self.cache[key] val self.rec[key] rec return val def put(self, key: int, value: int) - None: if key in self.cache: self.cache.pop(key) self.rec.pop(key) elif len(self.cache) self.capacity: oldest_key next(iter(self.cache)) self.cache.pop(oldest_key) self.rec.pop(oldest_key) self.cache[key] value self.rec[key] time.time()这段代码能跑通基本功能但严格来说它只保证“逻辑上的LRU顺序正确”因为Python字典本身维护插入顺序每次get时先pop再插入可以模拟出最近使用顺序。不过我建议笔试或面试时还是写经典的双向链表版本因为面试官想看到的是你能自主设计数据结构而不是依赖语言特性。这里有个实际经验笔试的时候如果你时间不够写一个“能跑但不够优雅”的版本比写一个“优雅但没写完”的版本得分高很多。在线判题系统按测试用例给分部分通过也有分千万别空着不写。3.2 编程题两个有序数组的中位数这题在LeetCode上是第四题工程卷里偶尔会出现。题目很简单给定两个大小分别为m和n的有序数组找出它们合并后的中位数要求时间复杂度O(log(mn))。最直观的做法是合并两个数组后取中间位置时间复杂度和空间复杂度都是O(mn)但题目一看就知道是要考二分。核心思路是把问题转化为“在两个有序数组里找第k小的数”。每一轮比较A[k/2-1]和B[k/2-1]谁小就排除谁前面的那一半元素k随之减半直到k为1或其中一个数组为空。这个算法每轮把k减半所以整体复杂度是O(log(mn))。笔试的时候要注意几点一是边界条件非常容易写错比如k/2可能超过数组长度需要取min二是中位数的奇偶处理可以统一用找第(mn1)/2和第(mn2)/2个数的平均值省去分类讨论三是别想着用暴力解法“先求个大概”因为时间复杂度有明确要求暴力做法过不了全部测试用例。这类题就是典型的“思路对了代码一气呵成思路不对卡到交卷”。注意这道题如果你在笔试现场真的卡住了有一个折中策略先用O(mn)的归并法写一版能过的代码把分数拿到手如果还有时间再优化成二分。能拿满分最好拿不到满分也比交白卷强。3.3 设计题短链接系统怎么答设计题是工程A卷里最能拉开差距的部分。举个例子让你设计一个短链接生成系统。这种题没有标准答案考察的是你能否从零到一搭建一套完整方案。我建议按下面这个顺序答题第一步是需求分析。先点名核心功能长链接转短链接、短链接重定向回长链接。再补充非功能需求比如QPS大概多少、数据量多大、是否要过期时间。千万不要跳过这步直接画架构因为后续所有设计都依赖这些假设。第二步是数据模型。最简单的是两张字段的表短码和长链接映射表id、short_code、long_url、created_at、expire_at。索引建在short_code上查询走唯一索引。这里要提到为什么用short_code做唯一索引而不是id因为重定向请求是通过short_code来定位记录的。第三步是短码生成方案。常见方案有三种随机字符串、哈希取模、发号器。随机字符串简单但可能冲突要加唯一索引或查重视试哈希取模可以用MD5后截取前几位发号器则依赖数据库自增或Snowflake本质是维护一个全局递增ID然后把十进制ID转成62进制字符串。我通常推荐发号器方案因为可控性好无碰撞性能也稳定。第四步是重定向流程。用户访问短链接时网关层接收请求查缓存命中就直接返回302跳转缓存没命中则查数据库回填缓存并返回。这里要顺带说一句缓存的Key设计、过期时间、缓存穿透的应对方式哪怕只提一句也能让面试官觉得你有全局视角。第五步是扩展性。可以提到统计点击量、增加异步任务清理过期数据、短码预生成或批量发号来提升写入性能。这些属于加分项优先级低于前三步但能体现工程经验。方案优点缺点适用场景随机字符串实现简单无需额外组件可能冲突需要重试低并发、量小哈希取模无需发号器自控短码碰撞处理复杂分布可能不均短码长度固定发号器无碰撞性能稳定需要额外维护发号组件高并发、大规模注意设计题最忌讳天马行空。别一上来就说“用Redis”“用消息队列”“上Kafka”要先说清楚为了解决什么问题才引入这些组件。面试官在看笔试解答时要看的不是技术名词的数量而是你能不能把每个决策和业务需求对应起来。4. 笔试过程中的时间管理与避坑技巧笔试不只是考你会不会还考你两小时内怎么分配精力和踩坑后能不能快速恢复。这一节聊聊实战技巧都是我自己和周围同学用教训换来的。4.1 两小时怎么分配最合理工程A试卷整体时间一般在90到120分钟。我的建议是选择题控制在20到30分钟编程题从最简单那道开始做起两题之间不留超过10分钟的空窗期设计题至少留20分钟。很多人一上来就把选择题全部做完结果最后编程题来不及。反过来也有少部分人先死磕难题结果简单题没时间写。最优策略是先把整张卷子扫一遍标记出每道题的难度然后按“简单编程题、选择题、第二道编程题、设计题”的顺序推进。这里有个朴素的道理编程题AC一道顶得上选择题对十道因为选择题每题分值小编程题是按测试用例百分比给分的做对一半就有50%分值。4.2 我踩过的5个典型坑第一审题不清。题目说的是“有序数组”我没注意直接当普通数组做了个排序浪费了不必要的复杂度。第二边界条件漏判。比如链表的头节点为空、数组只有一个元素、数字溢出这些情况在笔试中非常容易漏而判题系统特别喜欢在这些边界上放测试用例。第三死循环。写while循环时没有更新循环变量或指针一运行就超时。第四以为在线编辑器会帮你检查类型。笔试用的在线编辑器很多没有本地IDE那么智能变量名拼错要到运行才能发现白白浪费时间。第五心态崩掉。一道题卡了半小时后面全乱套。这些坑我基本都踩过尤其是心态问题。后来我总结出一个方法卡住超过15分钟就换下一道回头再想。短暂离开难题往往会让思路重新打开。笔试过程中不要执着于“必须这道题满分”你的目标是整张卷子的总分最大化。4.3 笔试结束后的复盘与面试衔接笔试一结束很多人的反应是“终于解脱了”然后把题目忘得一干二净。这是最亏的。笔试结束后趁热打铁复盘是秋招提升能力的最佳时机。我当时每做完一场笔试都会立刻把编程题重写一遍不管是暴力解还是最优解然后整理到自己的笔记里。这些笔记后来在面试时帮了大忙。笔试也会影响面试。有些公司面试官手里会有你的笔试记录包括做题时间和通过率。面试时主动聊笔试里那道设计题说“我当时考虑不周后来想到可以这样改进”会让面试官觉得你有自驱力。这比被面试官追问时支支吾吾好得多。反过来如果你笔试没过但把题目都吃透了后续面其他公司遇到类似题型也会感谢当时认真复盘的自己。5. 回到“工程”本身校招准备的长期路线这一节我想跳出具体题目聊一聊怎么系统性地准备这类工程岗笔试。很多同学在秋招前两三个月才开始刷题时间紧任务重很容易焦虑。我按时间维度和能力维度各给一份路线参考。5.1 三个阶段的时间规划如果距离秋招还有半年可以按三个月、两个月、一个月来拆。前三个月是基础期把数据结构、操作系统、网络、数据库四门课过一遍同时保持每周至少三道编程题的手感。中间两个月是专题期按LeetCode的tag刷题每个专题集中攻克配合面经查漏补缺。最后一个月是模拟期每天掐时间做一套真题或模拟题练手速和心态。编程题的量不需要追求“刷完LeetCode”重点是每道题都要吃透。我见过刷了五百道题的同学笔试考崩也见过只刷了两百道但每道都反复嚼过的同学通过。关键不在于数量而在于你能不能把一道题的思路迁移到新题上。比如你掌握了“用堆解决TopK”这个模型那“求前K个高频元素”“合并K个有序链表”“数据流中的中位数”这些题本质上都是同一个模型的变形。如果时间只剩一个月也不要慌。把精力集中在最高频的题型上链表操作、二叉树遍历、动态规划入门、LRU缓存、TopK问题。这些题目出现频率极高练熟它们至少能保证你在笔试中不交白卷。5.2 工程能力的核心思考方式最后想多说一句笔试只是校招的入口真正决定你能走多远的是工程能力本身。工程能力强的人通常有一种共性——遇到问题先拆解再逐个击破。面试官问“线上服务变慢了怎么办”不是想听一个神奇命令而是想看你能不能把“变慢”拆成网络、CPU、内存、磁盘、数据库、代码逻辑几个层面再逐一排查。这种思考方式在笔试设计题里同样适用。拿到一个开放问题不要慌按“需求→数据→算法→架构→扩展”的路径走哪怕你给不出最完美的方案只要结构完整、逻辑自洽就已经超过了大部分候选人。我后来给新同学做校招模拟面试时经常看到有人一拿到设计题就急着画架构图结果连“这个系统解决什么问题”都没说清楚。这就像写代码不先想清楚接口定义就直接写实现大概率会返工。所以在准备笔试的时候除了刷题我还建议你多问自己几个“为什么”这个数据结构为什么适合这个场景这个算法的时间复杂度为什么是这么多如果数据量大十倍这个方案还成立吗带着这些问题去复习你掌握的不再是一个个孤立的知识点而是一套可以复用的工程思维。我自己在准备秋招那阵子曾经刷题刷到怀疑人生。后来发现真正让我通过笔试的不是某一道题的解法而是我养成了“先想清楚再动手”的习惯。这份工程A卷表面考的是知识点深层考的其实是这个习惯。最后再说一个备考细节笔试前一定要模拟真实环境用在线编辑器做几套题不要一直依赖本地IDE的自动补全和编译提示。很多同学平时刷题顺风顺水一到笔试就水土不服就是因为不习惯没有自动补全的裸写环境。提前适应能帮你省下大片在考场上骂自己的时间。
返回列表