2023年飞猪秋招工程岗笔试,是我校招季里印象最深的一场。飞猪是阿里旗下的在线旅游平台,工程岗笔试走的是集团统一笔试的流程,整体风格跟互联网大厂的技术笔试非常接近。题型集中在单选、多选和两道编程题上,考察范围覆盖数据结构与算法、Java基础、计算机网络、数据库和操作系统这些计算机核心课,外加少量逻辑题和场景题。
这篇文章我想用过来人的视角,把这场笔试从题型分布到知识点侧重,从编程题思路到避坑经验,完整复盘一遍。不管你是准备冲明年的春招秋招,还是单纯想看看大厂技术笔试到底考什么,这篇都能给你一个比较完整的参考。我会尽量把每类题目背后的考点逻辑也讲清楚,而不是简单说“考了哪些题”。
1. 笔试的整体情况与备考目标
1.1 飞猪秋招工程岗笔试的整体流程
先说说这场笔试是怎么安排的吧。飞猪的秋招笔试一般走的是阿里集团统一招聘系统,网申通过简历初筛之后,会收到一封笔试邀请邮件,里面会指定考试时间段和使用的在线笔试平台。我当时用的是集团自研的在线评测系统,不是牛客也不是赛码,界面比较简洁,左侧是题目列表,右侧是代码编辑区,支持Java、C++、Python几种主流语言切换。
整个笔试时长为90分钟,题量大概是20道左右的选择题加2道编程题。选择题里包含单选和多选,多选一般会明确标注“不定项选择”,少选、错选都不得分,这对知识掌握的准确性要求比较高。编程题的分值占比很大,两道题加起来将近一半的分,基本可以说编程题决定了你能不能过笔试这一关。
需要提前说明的是,飞猪工程岗的技术栈以Java为主,所以笔试题目的语言偏向Java体系是正常的,比如集合源码、JVM、并发工具这些在选择题里出现的频率明显高于C++岗位。但编程题本身不限语言,用你熟练的语言写就行,重点看思路和代码正确性。
1.2 题目结构与时间分配
这份卷子的题目结构我复盘下来大概是这样的:选择题部分偏重基础知识的广度,前几道通常是比较简单的数据结构题,比如栈和队列的特性、二叉树遍历的复杂度,中间穿插几道Java基础题,后面会突然出现一两道偏门题目,比如“以下哪个是Spring Bean的默认作用域”这种偏框架的题,或者是“某个Linux命令的作用”这种偏运维的题。整体难度是梯度上升的,前面别犹豫太久,不然后面会紧张。
时间分配上,我的建议是:选择题部分控制在40分钟以内,每道题平均不超过2分钟。遇到拿不准的题先在草稿纸上标记一下,跳过去做后面的,不要在一道题上死磕。编程题留出大概45分钟,每道题20分钟左右,剩余5分钟用来检查代码格式和边界情况。如果第一道编程题卡了超过25分钟,果断先跳过做第二道,因为很多情况下第二道题反而更简单,分值却是一样的。
这里说一个我当时观察到的细节:同一场笔试里,每个人的题目顺序可能不一样,有些人的编程题出现在前面,有些人在后面,所以拿到卷子先花一分钟扫一遍整体结构,心里有个数,不用被顺序带乱节奏。
2. 核心知识模块逐个拆解
2.1 数据结构与算法:这是拉分的关键
数据结构与算法在选择题和编程题里都是重头戏,选择题里大概占了30%左右。链表、栈、队列、二叉树、图、排序、查找、动态规划、贪心这些基本都会覆盖到。我印象比较深的几道题包括:给定一个二叉树的中序和后序遍历序列,让求前序遍历;一个关于最小生成树Kruskal算法的时间复杂度;一个关于哈希表冲突处理方式的判断题。
这些题本身没有特别难,但要拿满分也不容易。比如那道中序遍历与后序遍历求前序的题,如果你只是背过“左根右”“左右根”的序列顺序而没有真正理解递归构建二叉树的过程,现场推导很容易乱。我的经验是,备考阶段一定把树相关的递归逻辑在纸上画熟,特别是根据两种遍历序列还原二叉树这类经典题型,要能做到一分钟内推出结果。
算法的选择题里还有一个高频考点是排序算法的稳定性与时间复杂度对比。这里强烈建议大家把一张汇总表背熟练:快排平均O(nlogn)、最坏O(n²),不稳定;归并排序稳定但空间复杂度O(n);堆排序时间复杂度稳定在O(nlogn)但不稳定。飞猪笔试里考到了堆排序和快排的稳定性比较,这类题属于纯记忆加理解的题型,掌握了就是送分题。
2.2 Java基础与并发:工程岗的核心侧重
飞猪毕竟是阿里系,对Java基础的考察深度是有的。HashMap在JDK 7和JDK 8中的底层结构差异、扩容机制、红黑树引入的条件,ConcurrentHashMap的锁分段与CAS实现,JVM内存区域的划分,垃圾回收算法与常见收集器的区别,这些大概率会出现。我当时就遇到了一个关于HashMap在JDK 8中链表转红黑树的阈值问题,答案是8,这个数字你光靠理解是记不住的,必须专门背。
线程池这块也是高频考点。线程池的核心参数含义、任务提交流程、四种拒绝策略分别适用于什么场景,都需要熟练掌握。我记得有一道多选题问的是“关于ThreadPoolExecutor的说法正确的有哪些”,选项里混合了核心线程数设置、阻塞队列类型、拒绝策略触发条件等细节。这类题的难度在于选项之间的干扰项设置得很细,只背概念不够,最好亲自写个demo跑一遍看线程执行顺序。
JVM内存模型方面,堆、栈、方法区、程序计数器各自的职责,哪些区域会发生OOM,哪些是线程共享的,这些都是基础中的基础。我记得有一道题考的是“以下哪个区域不会抛出OutOfMemoryError”,答案是程序计数器,这个考点在各大厂的笔试里出现了很多次。如果你准备时间有限,JVM这块优先保内存模型和垃圾回收的基本流程,因为可考的点就那几个,反复出。
2.3 计算机网络与操作系统:不能丢的基本盘
计算机网络这边,TCP三次握手和四次挥手算是必考题,但飞猪考得稍微有点变化,我记得有一道题不是直接问“为什么要三次握手”,而是给了一个TCP连接建立过程的描述,让判断哪个环节出错了。这种考法比直接背概念要灵活一些,需要你真的理解SYN和ACK的关系,而不是死记步骤编号。
HTTP协议也是重点,尤其是HTTP和HTTPS的区别、GET和POST的区别、状态码的含义。有一道题考的是“以下哪个HTTP状态码表示服务器内部错误”,答案是500,但选项里混了301、302、403这些,基础不扎实的人容易选错。另外阿里的技术体系里经常提到HTTP/2的多路复用,笔试里如果出现不要慌,它本质上就是解决队头阻塞问题的特性。
操作系统这边的考点集中在进程与线程的区别、死锁的四个必要条件、虚拟内存与分页机制、进程调度算法。我遇到一道题是给了几个关于死锁的叙述,让选出错误的那个,选项里涉及了互斥条件、持有并等待条件、不可剥夺条件和循环等待条件。这类题需要把四个必要条件背熟,并且理解它们本质上是AND关系,缺一个都不会死锁。
2.4 数据库与场景设计:贴近业务的考察
数据库的考题主要集中在索引、事务、SQL语法和范式上。InnoDB的B+树索引结构、聚簇索引与非聚簇索引的区别、最左前缀原则、事务的ACID特性和隔离级别,这些都是高频考点。飞猪的场景是旅游电商,业务上订单、库存、支付这些模块天然对数据库要求高,所以数据库的题目并不是纯理论,有些会结合场景来出。
举个例子,我当时遇到一道场景题大意是:一个订票系统在高并发下出现了超卖问题,问可以通过哪些手段解决。选项里有乐观锁、悲观锁、Redis预减库存、数据库唯一约束等。这类题表面上是考数据库隔离级别和锁机制,实际上是在考你对分布式系统下并发控制的理解。我在笔试时遇到这道题挺兴奋的,因为自己在学校做过一个秒杀项目的demo,虽然是简化版,但思路是通的。
SQL语法方面,多表联查、子查询、GROUP BY与HAVING的组合是基本操作,group by的考察点有时候会绕一下弯,比如“查询每个城市的订单总数并筛选出超过1000的城市”,底层考的就是WHERE和HAVING的执行顺序问题。如果你平时写SQL依赖ORM框架,笔试前一定要手写一遍这些经典SQL,不然考场上一紧张连SELECT语句的顺序都会写岔。
3. 编程题实操:一道题讲透一类题
3.1 真题回忆:TopK问题与最小堆
两道编程题我还能比较清晰地回忆起来,因为第一道就是个很典型的算法题,第二道则带一点工程化的味道。先说说第一道吧:题目大意是给定一个无序整数数组和一个整数k,要求找出数组中第k大的元素。
这道题我第一反应是直接排序取下标,但这显然不是出题人想看到的答案。如果要考察排序,题目就直接说用数组排序了。第k大这种问题在Web后端面试里出现频率极高,因为它在搜索引擎、排行榜、推荐系统里都有实际应用场景。飞猪这种旅游平台,促销活动上线的时候,实时热门目的地排行榜就是典型的TopK问题。
3.2 解题思路与代码实现
我当时采用的思路是维护一个大小为k的最小堆:先遍历数组前k个元素建堆,然后从第k+1个元素开始,每个元素跟堆顶比较,如果比堆顶大,就替换堆顶并调整堆结构,最后堆顶就是整个数组中第k大的元素。这个思路的时间复杂度是O(nlogk),比排序的O(nlogn)要好,尤其在k远小于n的场景下优势非常明显。
Java代码里我用的PriorityQueue实现最小堆,这个类是Java里现成的堆数据结构。但要注意的是,PriorityQueue默认是小顶堆,如果题目要第k小的元素,就需要传入自定义比较器变成大顶堆。这个细节在笔试里容易踩坑,我当时就特意检查了一遍构造函数的参数。
public int findKthLargest(int[] nums, int k) { // 默认小顶堆,堆顶是最小值 PriorityQueue<Integer> minHeap = new PriorityQueue<>(k); for (int num : nums) { if (minHeap.size() < k) { minHeap.offer(num); } else if (num > minHeap.peek()) { minHeap.poll(); minHeap.offer(num); } } return minHeap.peek(); }这道题有个隐含考点是k的合法性判断。题目一般会说1 ≤ k ≤ 数组长度,但如果你平时没有检查边界条件的习惯,可能在数组为空或k越界的时候报错。我在笔试时习惯在方法开头加一个鲁棒性判断:
if (nums == null || nums.length == 0 || k <= 0 || k > nums.length) { return -1; }虽然笔试判题系统可能不会特意测这些边界,但养成这个习惯对整个代码风格是加分的。
另外,基于快速排序的partition思想也可以解这道题,平均时间复杂度能优化到O(n),但最坏情况会退化到O(n²)。我当时没有用它,因为堆排序的思路对面试官来说更容易确认你理解了数据结构,而且代码更好写,不容易出bug。笔试时间紧的情况下,选择稳妥的方案远比追求最优解重要。
3.3 第二道编程题:贴近业务的模拟场景
第二道编程题我记得是一道字符串处理的题,大意是给定一组用户的访问记录,每条记录包含访问时间和访问页面,要求统计出指定时间窗口内的去重访问用户数。这道题本质上考察的是HashSet去重和时间字符串的解析比较。
这类题目看起来像LeetCode上的题,但实际考察的是工程上常见的业务模型:网站的UV统计。飞猪平台上有大量景点页面、酒店页面、机票页面的访问日志,精确去重统计用户数正是大数据分析的基础。理解了这层业务背景,你写代码的时候就会明白为什么出题人要把输入输出格式设计成那样。
实现思路其实不复杂:用HashMap存储“日期-用户ID集合”的映射,每一天对应一个HashSet,只需要把用户ID添加到对应日期的集合里,最后取集合大小即可。但有个细节需要注意,用户ID和访问时间之间用什么分隔符解析,日期格式是“yyyy-MM-dd”还是“yyyy/MM/dd”,这会影响substring和split的参数,一个字符的差别就可能导致解析错误。
我当时在这个字符串解析上耽误了一点时间,因为题目的输入示例不仔细看容易搞错分隔符。我的经验是,拿到编程题先不要急着写代码,花30秒读清楚输入格式,然后用纸笔推一个最简单的用例,确保自己的解析逻辑是对的再动手。这个习惯帮我避了很多次坑。
4. 常见问题与避坑指南
4.1 时间分配失衡:最容易犯的错
在笔试圈子里有个说法叫“选择2小时,编程1小时”,说的就是很多人沉迷于选择题的纠结,最后编程题没时间写。大厂笔试的选择题里有一些本来就是用来筛人的偏怪题,比如某个不常用的Linux命令参数、某个冷门的Java类库方法,这种题花再多时间也未必能蒙对,不如直接选一个最像的继续往下走。
我当时给自己定的规则是:一道选择题思考超过2分钟还没思路,立即标记并跳过。整套题的完成速度优先级永远高于单题的完美度。因为选择题的得分是累计的,而编程题只要你写出来主逻辑,哪怕有一些小bug没调试通过,也能拿到部分分数。从成本收益的角度看,编程题的性价比远高于偏怪选择题。
4.2 多选题的漏选错选陷阱
选择题里有几道不定项选择题,这是最容易失分的地方。不定项选择的计分规则通常是选对但不全得一半分,选错一个就全扣。也就是说,如果你对某个选项没有十足的把握,不要因为它看起来像正确答案就选上,宁可少选也不要去赌。
我遇到的一道不定项题是关于Java垃圾回收的,选项里提到“System.gc()一定会触发Full GC”“G1收集器可以指定暂停时间目标”等。第一个说法明显是错误的,因为我记得System.gc()只是建议JVM执行垃圾回收,并不保证一定执行Full GC。这种题就是考你对概念精确边界的把握程度,模糊记忆会导致多选错选。备考阶段专门整理一个“易混淆知识点清单”很有用,把这类模糊概念逐一敲实。
4.3 编程题的输入输出环境
在线笔试最容易让人慌张的其实是输入输出环境,尤其是平时刷LeetCode刷惯了“函数式”做题法的人,突然让你处理标准输入输出,一开始会发懵。飞猪这套系统是需要自己写Main类和完整的输入解析逻辑的,不是像LeetCode那样只写核心函数。
考前一定要花点时间熟悉Java的Scanner和BufferedReader两种输入读取方式,以及System.out.println的输出规则。我个人的习惯是用BufferedReader加split解析整行输入,因为Scanner在面对大量输入的时候性能略差,笔试虽然不会刻意卡性能,但万一数据量较大,Scanner可能因为nextInt和nextLine混用导致读入错位。
另外要注意的是,题目给的输入示例通常是有规律的,比如第一行是测试用例组数,后面每一组是一行数据。解析的时候建议用一个List把每组数据存起来,而不是处理一行输出一行结果。这样方便统一调试,也符合“先读入再处理”的工程习惯。
4.4 备战时间规划:三周冲刺方案
如果你离笔试还有三周左右的时间,我的建议是这样安排:第一周集中刷数据结构和算法的基础题,重点是数组、链表、树、栈、队列、哈希表、排序和二分查找;第二周深入Java基础、并发和JVM,配合看一些源码分析文章,同时开始刷数据库和计算机网路的题;第三周进入冲刺模式,每天一套完整模拟题,练手感和时间分配。
刷题平台的选择上,LeetCode的Hot 100题目覆盖了大厂笔试的大部分算法题型,牛客网的Java方向题库对选择题的题型覆盖比较全面,再有时间可以看剑指Offer的经典题型。但不要贪多,宁可每个题型做透20题,也不要泛泛刷300题什么都没记住。
我觉得还有一点很重要:调整好心态。笔试本质上是筛选机制,不是选拔机制。你不需要答满所有的题目,只需要比同批竞争的人正确率更高就行。遇到不会的题再正常不过了,保持冷静,把自己能拿的分稳稳拿到手,就已经赢了大部分人。
5. 笔试之后的面试衔接准备
5.1 笔试到面试的间隔:别松劲
笔试毕竟只是校招路上的第一关,通过笔试之后通常一周到两周内会收到面试邀约。这个间隔说长不长说短不短,很多人笔试完了就开始躺平,等到面试通知来了才发现项目经历一团乱麻、八股文背不熟,结果白白浪费了前期积累的优势。
我的建议是笔试结束当晚就把考过的知识点整理一遍,尤其是那些让你犹豫不决的题,问一下自己:这道题我到底是因为不会丢分,还是因为紧张看错了题干?如果是知识点盲区,立即补上,因为面试环节大概率会追着笔试中的薄弱点继续深挖。比如笔试里出现了ConcurrentHashMap的CAS操作相关题目,你不太确定,那面试前必须把ConcurrentHashMap在JDK 8中的put流程完整梳理一遍。
5.2 项目经历的准备:别让笔试白考
飞猪工程岗的面试环节非常看重项目和实战能力。笔试只是入门券,面试才是分胜负的地方。我当时在笔试结束后重新梳理了自己的项目,重点提炼了几个和旅游电商场景相关的能力点:高并发下的接口优化、缓存与数据库的一致性方案、订单状态的机状态机设计等。
这里分享一个技巧:把你做过的项目按STAR法则整理成一张表,每个项目写出背景、任务、动作、结果,并预判面试官可能追问的3个问题。飞猪的面试官喜欢围绕你写的项目深挖细节,比如“你这个接口的QPS是多少”“如果流量翻十倍你怎么办”“缓存过期瞬间有大量请求怎么办”,这些问题如果从来没想过,现场很难编出合理答案。
笔试里考到的数据库锁机制、性能优化思路,在面试项目中完全可以复用。比如你可以在项目介绍里主动提到秒杀场景下如何用乐观锁避免超卖,或者如何用Redis做热点数据的缓存降级,这些都是飞猪业务非常相关的技术点,面试官听到会眼前一亮。
写在最后:一些个人体会
回看这次飞猪秋招笔试,我觉得最有价值的不是最后拿到了什么样的成绩,而是它让我重新审视了自己对计算机基础知识的掌握程度。大学期间写业务代码练了很多,但真正面试时发现,基础不牢的代价是举步维艰。笔试不会因为你项目里用了某个热门框架就给你加分,它只看你对操作系统、网络、数据结构这些底层知识有没有理解透。
还有一个小技巧想分享给看到这里的你:平时刷题和做笔试的时候,养成在代码里写注释的习惯。笔试系统的代码编辑器通常没有智能提示,代码全靠手敲,而注释可以帮你在紧张状态下快速回忆逻辑。而且面试官在复盘笔试代码时,看到清晰的注释会认为你是一个代码规范意识强的人,这在后续面试中是一个隐形的加分项。
希望这篇复盘能对你准备飞猪或其他大厂的技术笔试有一点帮助。不要把它当成一次考试,把它当成一次对自我知识体系的全面检验。基础打牢了,机会自然会来。