先说结论:饿了么2024年秋招终端岗的笔试,整体难度在互联网大厂里属于中上,没有特别偏门的题目,但考察面很广,对基本功要求不低。如果你正在准备25届或者26届的秋招,这篇复盘应该能帮你少走不少弯路。
我投的是终端方向,笔试用的是牛客网在线测评,全程摄像头监控加屏幕录制,时长大概120分钟,题型分布是单选题、多选题、填空题加两道编程题。单看题型好像挺常规,但真正坐下来做题的时候,你会发现它考的不只是“会不会”,而是“熟不熟”。终端岗的考察重点和后台、算法岗有明显区别,它更看重你对运行机制的理解、对资源的敏感度,以及在实际工程里踩过多少坑。
这篇文章我按自己的备考经历和复盘记录来写,从笔试题目类型、核心知识点拆解、编程题解题思路、备考方案,到踩坑记录,完整走一遍,给后面要参加类似笔试的同学做个参考。
1. 整体设计与备考思路
1.1 笔试基本信息与考察范围
先说流程。饿了么的秋招笔试通知一般提前2到3天发到邮箱和短信,你需要提前在牛客网上把环境测试好。我当时遇到的一个小插曲是摄像头驱动一直识别不了,后来换了Chrome浏览器、关闭所有后台占用摄像头的软件才解决。这里提醒一句:笔试当天不要开任何屏幕共享类工具、弹窗拦截软件,否则很容易被判作弊。
从题目范围来看,终端岗笔试大致覆盖了五个方向:
- 计算机基础:操作系统、网络、数据结构与算法
- 前端方向:JavaScript、浏览器原理、CSS/HTML、框架(React/Vue)
- 客户端方向:Android/iOS基础、跨端方案、内存管理、多线程
- 工程化与监控:构建工具、CI/CD、埋点、稳定性治理
- 场景题与开放题:定位线上问题、性能优化、架构设计
选择题里面,前端的比重会比客户端略高一些,这可能和饿了么终端团队的技术栈有关,Web端和移动端都有大量业务依赖。但即便是客户端方向的题目,也逃不开JavaScript和浏览器相关的考察,所以别指望只抱着一本《Android开发艺术探索》就去考试。
1.2 为什么考这些:从企业视角看考察逻辑
我刷完题之后复盘,发现这些题目背后其实有一套很明确的筛选逻辑。终端岗最核心的诉求是:在复杂的业务场景下,保证用户体验流畅、稳定、可监控。所以笔试不会只问你“这段代码输出什么”,而是会反复从“内存、性能、并发、稳定性”几个角度出题。
比如操作系统里考死锁、进程调度,不是单纯背概念,而是希望你理解App卡顿、ANR、资源竞争背后到底发生了什么。网络里考TCP握手、HTTP缓存,是因为终端的每一个请求都直接影响页面加载速度和省流量策略。框架里考虚拟DOM、diff算法、响应式原理,是因为实际业务里列表渲染、状态管理真的会遇到性能瓶颈。
所以我的建议是:备考时不要孤立地记知识点,而是每学一个东西,都问自己一句“这个知识点在终端开发里解决了什么问题”。带着这个问题去复习,你会发现选择题的命中率会高很多。
2. 核心笔试模块拆解
2.1 JavaScript与前端基础:从语言特性到浏览器原理
JavaScript在终端岗笔试里的分量,大概能占到选择题的三分之一。考察的点比较集中,首先是语言本身的特性:原型链、闭包、事件循环、作用域、this指向、类型转换。这些题目看起来简单,但很容易在细节上翻车。
举个例子,题目给了这样一段代码:
for (var i = 0; i < 5; i++) { setTimeout(() => { console.log(i) }, 100) }问输出结果。如果你只答“5个5”,那只能算基础过关。它还会接着问:改成let会输出什么?如果不用let,怎么用闭包解决?用Promise怎么实现顺序输出?这几个追问才是真正的区分度所在。
浏览器原理方面,考得比较多的是渲染流程、回流和重绘、事件委托、浏览器缓存机制、跨域方案。其中缓存机制几乎每年必考:强缓存和协商缓存的区别、Cache-Control和Expires的优先级、ETag和Last-Modified的对比,这些都是终端性能优化的基石。我在复习时把这些整理成了一张对比表,非常管用。
| 缓存类型 | 主要字段 | 触发条件 | 优点 | 缺点 |
|---|---|---|---|---|
| 强缓存 | Cache-Control、Expires | 未过期直接使用本地缓存 | 不发起请求,速度最快 | 服务端更新后客户端无法感知 |
| 协商缓存 | ETag、Last-Modified | 强缓存失效后携带条件请求 | 能感知服务端变更 | 每次都要发请求,多一次往返 |
框架方面,React和Vue都会涉及,但深度不算特别深。React重点在虚拟DOM、diff算法、生命周期(现在更多考Hooks的依赖收集)、受控组件和非受控组件。Vue重点在响应式原理、依赖收集、nextTick、computed和watch的区别。我建议把两个框架的核心原理路线图自己在纸上画一遍,画得出来,才算真懂了。
2.2 客户端基础与跨端能力:内存、线程与原生交互
客户端方向的选择题,考得比较密集的是内存管理、多线程、消息机制和跨端方案。
Android方向常考的有:Activity的启动模式和生命周期、Handler的机制(Looper、MessageQueue、Message)、内存泄漏的常见场景、垃圾回收机制、进程间通信(Binder、AIDL)。iOS方向常考的有:Runloop、ARC和MRC、循环引用、GCD和NSOperation的区别、KVO和KVC的实现原理。
如果你只准备了其中一个平台,也千万不要放弃另一个平台的基础题。因为饿了么是本地生活超级App,业务形态非常复杂,终端团队里既有Android也有iOS,还有做跨端框架的。笔试里出现“Flutter和React Native的渲染机制有什么区别”“小程序双线程模型了解吗”这类题目,一点都不意外。
跨端方案这块,最近两届秋招的热度明显在上升。Flutter的Skia自绘引擎、RN的JSBridge通信、小程序的双线程模型(逻辑层和渲染层分离),这些概念最好能用自己的话讲清楚,甚至能画出它的架构图。选择题里它往往会结合性能问题来考,比如:“为什么Flutter的滚动性能比RN更稳定?”本质是渲染通道不同,Flutter直接走Skia,绕过了原生控件的布局系统。
2.3 网络、操作系统与工程化:终端开发者的底层内功
网络部分,重点在TCP/UDP、HTTP/HTTPS、DNS解析、WebSocket。TCP三次握手和四次挥手属于必背内容,但近几年笔试更喜欢结合题目场景来考,比如“在弱网环境下,为什么TCP的拥塞控制算法会导致请求变慢?”“如何优化HTTPS的握手耗时?”这类问题没有标准背诵答案,需要你真正理解协议的设计意图。
操作系统方面,进程和线程的区别、死锁的四个必要条件、虚拟内存和物理内存的映射、常见的调度算法(先来先服务、短作业优先、时间片轮转),这些都属于基础送分题。真正容易丢分的是它和终端场景结合在一起的时候,比如“App进程被杀掉后,为什么有些数据能恢复?这背后涉及Linux的什么机制?”这时候你要联想到进程的创建、Binder通信、以及AMS对进程的管理。
工程化方向,一般会考Git操作、Webpack/Vite的打包原理、CI/CD的基本流程、代码质量与埋点监控。比如:“Webpack的Loader和Plugin有什么区别?”“sourcemap在线上定位问题时的作用是什么?”“前端埋点一般有哪几种方案?各自的优缺点?”这些题不深,但你得真的在项目里用过、配过、踩过坑,才能答得准。
我当时在简历里写了“通过埋点系统定位线上白屏问题”,笔试就真的考了“如何设计一个前端埋点SDK,需要考虑哪些因素”。这提醒了我一个很重要的点:简历上写的每一个项目经历,都可能变成笔试里的场景题。所以项目一定要自己做、自己总结,不能背别人的项目经验。
3. 笔试编程题与解题思路
3.1 经典题目复盘:依赖解析与拓扑排序
第一道编程题是一个依赖解析问题,大致题意是:有一组任务,每个任务依赖若干个其他任务,给定依赖关系,输出一种合法的执行顺序。如果存在循环依赖,输出异常提示。
看到“依赖”“执行顺序”这两个关键词,就要立刻反应过来,这是典型的拓扑排序。我当时的思路是:
- 根据依赖关系构建邻接表和入度数组
- 将所有入度为0的任务先入队列
- 依次出队,把该任务指向的后继节点入度减1
- 入度变为0的任务继续入队
- 最后如果已执行的任务数量不等于总任务数,说明存在环
这道题的时间复杂度是O(V+E),空间复杂度是O(V+E)。在终端场景里,它对应的是“多模块打包时的依赖关系处理”和“启动任务初始化顺序”这两个真实问题。所以输入描述里就用“启动任务”“模块初始化”来包装,很多人没发现这层对应关系,硬生生当成纯算法题做,反而容易在边界条件上出错。
需要注意的边界点有三个:任务编号可能不是连续的(比如从0到n之间跳过某些编号);同一个任务可能被多个任务依赖;输入里可能出现重复的依赖关系,需要去重。我当时用了一个Set来存邻接表,避免了重复边的干扰。
3.2 经典题目复盘:字符串压缩与解压
第二道编程题是字符串压缩与解压,规则是:3[a]表示aaa,2[bc]表示bcbc,支持嵌套,比如2[a3[b]]表示abbbabbb。要求实现一个解压函数,并处理非法输入。
这道题考察的是栈的运用和字符串处理能力。我当时的做法是维护两个栈:一个存数字,一个存字符串。遍历原字符串时:
- 遇到数字,累加解析出完整的数字(注意可能是多位数,比如
10[ab]) - 遇到
[,把当前已经拼接的字符串和数字分别入栈,然后重置 - 遇到
],从栈里弹出数字和之前的字符串,把当前字符串重复n次后拼回去 - 遇到普通字符,直接拼到当前字符串
嵌套的情况自然就被栈的后进先出特性处理了。我还加了一个辅助函数判断括号是否匹配,避免出现3[a这种非法输入导致死循环。
这道题在终端场景里对应的其实是“大包体积优化中的字符串资源压缩”和“协议传输中的字段压缩”,虽然包装得很轻量,但说白了就是想看你能不能熟练使用栈解决嵌套结构问题。类似的题还有“实现一个简单的计算器”,强烈建议多练几道同类型的。
3.3 代码书写与调试技巧
笔试的代码编辑器不像本地IDE那么智能,没有自动补全,报错信息也比较有限。所以我总结了几个很实用的技巧:
第一,先在纸上(或者草稿区)把思路整理好再动手写。笔试时间紧张,但也不要上来就敲代码。先在注释里把步骤写清楚,后面写代码的时候思路会顺很多。
第二,所有函数入口都要做边界检查。空字符串、极端重复次数、嵌套层数特别深的情况,都要考虑到。竞赛选手经常栽在“90%的用例都过了,但就是不知道哪一两个边界用例挂了”。
第三,用稳定的时间复杂度换取正确性。笔试不是面试,不考虑你的代码是否最优雅,最终评判标准就是用例过没过。如果你能想出O(n^2)的暴力解法,但想不出O(n)的优化解,那就先把暴力解法写出来,拿部分分,不要在一道题上卡太久。
第四,小心全局变量的污染。笔试平台一般会用多个测试用例连续调用你的函数,如果你在函数外面定义了全局变量且函数内部直接修改它,第二个用例就会受影响。我当时就因为这个原因挂了一个用例,排查了好久才发现是全局变量没重置。
我建议平时刷题就用牛客网的在线编程环境练习,因为它和笔试题的输入输出格式几乎一模一样,甚至更难一些。熟悉的输入解析、输出格式、异常捕获方式,都能减少考试时的紧张感。
4. 实操备考方案与时间规划
4.1 高效刷题路线:三阶段递进法
我是从8月初正式开始准备秋招笔试的,整个备考周期大概5周。这里分享一条我梳理出来的刷题路线,适合有一定基础、但还没达到竞赛水平的同学。
阶段一(第1周):基础巩固。把所有笔试涉及的知识点列成清单,逐个过一遍。我用的资料是《JavaScript高级程序设计》前几章、图解HTTP、图解TCP/IP,配合一些免费的面试题仓库。这个阶段不追求刷题量,而是把所有概念性的东西先扫一遍,保证选择题不丢分。
阶段二(第2-3周):刷题强化。每天固定刷3到5道LeetCode中等难度的题目,重点关注数组、字符串、链表、二叉树、动态规划这几类。这里不要贪多,每道题要尽量把思路写清楚,并且尝试用两种解法解答。终端岗的笔试算法题一般不会超过LeetCode中等难度,所以不需要花太多时间在难题、偏题上。
阶段三(第4-5周):模拟实战。使用牛客网的历年真题和模拟题,严格按照考试时间来做。我大概做了6套完整的模拟题,每次做完都认真复盘:选择题里错的知识点整理成文档,编程题里没写出来的解法重新写一遍。这个阶段的提升是最快的,因为你会发现自己的薄弱点非常集中,补起来效率很高。
4.2 简历与项目准备的联动
笔试的备战不只是在题海里刷题,更是对简历项目的重新梳理。我花了整整一个周末,把简历上写的每一个项目都按照以下模板重新整理了一遍:
- 业务背景:这个项目解决什么问题,服务多少用户
- 技术方案:用到了哪些核心技术栈,为什么选这个方案
- 个人贡献:我具体负责哪些模块,做了哪些优化
- 量化结果:性能提升了多少,崩溃率降低了多少,页面加载时间从多少降到多少
这个过程帮了我很大的忙。因为选择题和编程题是机器判分,但场景题和开放题更看重你的工程思维,而工程思维往往就来自你对项目的理解深度。比如“如何设计一个通用的安装包体积优化方案”这种题,如果简历里有“对App进行包体积优化,将首包体积降低30%”的经历,你就有了说不完的素材。
还有一点,很多公司的笔试系统会允许你调试代码,但不会允许你切出页面去查资料。所以不要把希望寄托在百度上,所有内容都要装进脑子里。这个过程虽然痛苦,但确实是提升最快的阶段。
4.3 工具使用与环境准备
笔试环境这一块,很多人会忽略,但恰恰是最容易出问题的。我建议在正式笔试前,找一段完整的时间做一次全流程模拟:
- 确认网络稳定,最好有线网络加手机热点双保险(这里不涉及任何特定软件,只是多一层保障)
- 提前安装好牛客网指定的浏览器版本,关闭所有无关插件
- 测试摄像头和麦克风,确保能被测评系统正常识别
- 准备一个安静的独立空间,提前告知家人不要在笔试期间打扰
- 把身份证或学生证放在手边,有些笔试需要二次身份核验
如果你是使用学校实验室或图书馆的电脑,一定要提前一天测试权限。实验室电脑有时候有还原卡,重启之后所有软件都没了,这种坑一旦踩上,笔试基本就废了。
5. 常见问题与踩坑记录
5.1 笔试环境与流程问题
我身边有同学在笔试时遇到过“摄像头黑屏但系统不提示”的问题。这里总结一下常见问题,方便你们提前排查。
| 常见问题 | 可能原因 | 解决方案 |
|---|---|---|
| 摄像头无法开启 | 浏览器权限未开启 | 在地址栏右侧点击摄像头图标,选择允许 |
| 页面一直加载不出来 | 浏览器版本过低 | 换用Chrome/Edge最新稳定版 |
| 代码提交后没有反馈 | 等太久直接刷新页面 | 先记录当前代码到本地,再刷新重试 |
| 屏幕录制失败 | 隐私设置禁止录制 | 在系统隐私设置里允许浏览器录制屏幕 |
| 考到一半被强制交卷 | 超出规定时间未操作 | 每道题做完后尽快点击保存/提交 |
这些问题看起来都很基础,但考试时高度紧张,再碰上技术故障,心态很容易崩。我建议把常见的环境问题提前查好,甚至可以把解决方法抄在纸上放在电脑旁边,作为应急预案。
5.2 答题策略与心态问题
这里单独说一下答题策略。选择题和填空题建议控制在60分钟内,剩下的时间全部留给编程题。如果选择题遇到拿不准的,不要纠结太久,先标记出来,等编程题写完再回头思考。我自己的经验是,一道选择题超过2分钟还没思路,直接猜一个,因为时间成本太高。
编程题一定要先把第一道简单题做出来再做第二道。我当时第一题写了大约20分钟,第二题写了35分钟,剩余时间用来检查和补充边界用例。如果你在第二题上卡了超过20分钟,建议先回到第一题把一些可能出问题的用例再测一遍,先把基础分稳到手。
心态方面,我想说一个很多人的误区:秋招笔试是允许失败的,甚至是可以多次投递的。我认识的一些同学,第一次笔试发挥不好就心态炸裂,后面几场也发挥失常,其实非常可惜。笔试更像是一个“熟练度测试”,你练得越多,临场发挥越稳定,这是可以复利的。
5.3 一些独家的笔试小技巧
最后分享几个可能只有实际参加过多场笔试才会发现的细节技巧。
第一,巧用自定义测试用例。牛客网上传代码后,可以自己输入测试用例来验证。很多人只跑了题目自带的示例就直接提交,但实际上题目给的例子往往是最常规的情况,你完全可以用它验证一下边界:空输入、单字符、超长字符串、重复字符等等。这一个习惯能帮你多挽救很多用例。
第二,尽量别在代码里写System.out.println调试输出。有些笔试平台会把你的标准输出作为答案的一部分,如果你忘了删调试代码,明明逻辑是对的,结果却因为输出格式不对被判错。要调试的话,用平台的打印功能,提交前仔细检查一遍删干净。
第三,注意输入描述里的数据范围。数据范围决定了你该用哪种算法。假如n最大是10^5,O(n^2)大概率超时,你就得想O(n)或O(nlogn)的解法;如果n最大是100,暴力解就没问题。这个判断在笔试中能帮你快速选择算法方向。
第四,开放题不要留白。终端岗的笔试最后往往会有一两道开放性问答题,比如“如何设计一个App的启动优化方案”。这类题目没有标准答案,但哪怕你只写了三五行,也比空着强。它考察的是你的思考框架,不是标准答案。按照“问题定义→目标分析→方案拆解→落地验证→指标监控”的框架来答,一般都能拿到一个不错的分数。
写在最后
回想这届秋招的笔试备战过程,我最想说的一个体会是:终端岗笔试的核心不是“押题”,而是“底层思维”。你背过的每一个知识点、刷过的每一道题,最后都会在某个场景题里以另一种形式出现。把基础打牢,把项目吃透,保持稳定的心态,比什么都重要。
如果你也在准备终端方向的秋招,希望这篇复盘能帮你建立一个清晰的备考框架。别焦虑,按照自己的节奏一步步走,每一场笔试都是在把你推向更适合的位置。