每年校招季,都会有不少学弟学妹来问我同样的问题:在线教育公司的技术类笔试到底怎么准备?算法题占多少?计算机基础考不考?要不要专门去刷那些脑筋急转弯式的逻辑题?说实话,我一开始也以为这类公司的笔试跟大厂通用题差不多,真正把一批题目整理下来才发现,在线教育场景的业务题占比、选择题覆盖面、编程题的难度梯度,都有它自己的规律。这篇文章不聊虚的,直接结合题型分布、高频考点、做题策略和备考路线,把一场技术类校招笔试从拿到试卷到提交答案的完整过程拆清楚。无论你投的是后端、前端、客户端还是测试开发,这套思路都拿过去用就行。
1. 在线教育公司校招笔试题型的真实分布
1.1 选择题:覆盖面广,单题不深
大多数在线教育公司的技术笔试,第一部分都是选择题,数量通常在三十道上下,以单选为主、多选穿插出现。考察范围看着吓人,其实非常标准化:数据结构、算法复杂度、操作系统、计算机网络、数据库,再加一两道语言基础题。为什么不是深挖某一门?因为校招候选人来自不同背景,有科班的也有非科班转行的,笔试第一轮要解决的是“快速筛掉基础有明显短板的人”,而不是“找到某个方向的大神”。
我整理题目的时候发现,选择题的单题难度真的不高,但耐不住量大、面广。比如操作系统会考进程和线程的区别、死锁产生的四个必要条件、虚拟内存的页面置换算法;网络会考TCP三次握手的中间状态、HTTP常见状态码的含义、DNS解析流程;数据库会考索引失效场景、事务隔离级别、SQL执行顺序。这些题单独拿出来,任何一个认真学过的人都能答对,但连续做三十道,某个知识点的记忆稍微模糊一点,就会开始连错。所以准备这类选择题,核心不是刷难题,而是把本科课程里的“概念辨析”部分全部过一遍。
多选题是最容易扣分的地方。不少平台采用“漏选给部分分,错选零分”的规则,但也有很多平台只要选错一个就整题算错。我的建议是:遇到模棱两可的选项,宁可不选。尤其是一些带“一定”“必须”“全部”字样的绝对化描述,大多数情况下就是错误选项。
1.2 编程题:从签到题到压轴题的梯度设计
编程题一般两到三道,个别公司会放到四道。整体难度设计是递进的:第一道属于“签到题”,只要你写过代码就能做出来,通常是字符串处理、数组遍历、简单模拟;第二道开始上强度,常见的是哈希表、双指针、栈或二叉树遍历;最后一道往往是动态规划、贪心或者带业务包装的综合题,用来卡掉大部分候选人。
这里有一个很有意思的现象:在线教育公司的编程题特别喜欢业务场景包装。比如“给定一批课程的开始和结束时间,统计同一时刻最多有多少门课在进行”,这本质上是一道扫描线或堆的题;“把用户连续观看记录按天合并成若干区间”,本质是一道区间合并题。为什么要包装?因为笔试题目一般来自产研团队的真实需求提炼,出题人希望候选人看到业务问题能联想到对应的经典算法模型。
这样设计的筛选逻辑很清晰:签到题保证基础合格的人都有分拿,中间题区分动手能力,压轴题筛出算法功底扎实、临场不慌的人。多数人的分差就体现在最后一道题上,而最后一道题通常不是“会不会某种高级技巧”,而是“能不能快速把业务描述抽象成数据结构”。
1.3 不同技术方向之间的题型差异
虽然统称技术类笔试,但不同岗位的试卷侧重点差异还挺明显。下面这张表来自我收集整理后的归纳,不同公司细节会有出入,但大体方向是差不多的。
| 岗位方向 | 选择题侧重点 | 编程题语言要求 | 附加题型 |
|---|---|---|---|
| 后端开发 | 数据库、网络、操作系统 | C++/Java/Golang均可 | 偶尔有SQL题或场景设计题 |
| 前端开发 | 浏览器机制、JavaScript基础、网络 | 通常不限,JavaScript更好 | 偶尔有简答题,考事件循环和闭包 |
| 客户端开发 | 操作系统、内存管理、多线程 | Java/Kotlin/Objective-C均可 | 可能有一道线程同步相关题 |
| 测试开发 | 数据结构、网络、数据库 | 不限,Python常见 | 常见用例设计简答题 |
| 算法岗 | 概率统计、机器学习基础 | Python为主 | 模型推导或手写损失函数 |
后端方向要特别留意数据库题,有的公司会在编程题后面额外挂一道SQL题,让你写一段查询或改一个慢查询,现场手写SQL千万别慌,把基本语法写清楚就能拿大部分分。前端方向则要注意,选择题里偶尔会出现“这段代码输出什么”的JavaScript作用域与闭包题,平时不用控制台跑一遍很难答对。测试开发方向相对友好,但用例设计简答题很拉分,需要在答题里体现出“等价类划分、边界值、异常场景”这些方法论。
2. 算法题的高频解法与在笔试里的实战推演
2.1 最常出现的四类算法题
如果只允许我押四个方向,我会押:区间类、双指针、二叉树、基础动态规划。这四个方向几乎覆盖了在线教育公司笔试编程题的大部分题目,也是LeetCode中等题里最常遇见的模板。
区间类题目最常见的变体是合并区间、计算重叠区间、求最大重叠数。这类题的通用套路是先按起始位置排序,然后一次遍历维护一个“当前合并区间的右边界”,碰见新区间就看它的左边界有没有落在当前区间内,在就合并,不在就收尾重开。核心是理解排序过后相邻关系带来的单调性。
双指针的经典应用是滑动窗口和两数之和。滑动窗口尤其适合“连续子数组”“连续子串”这类条件统计题,先移动右指针扩大窗口,条件不满足时再移动左指针收缩,整个过程只遍历一次,复杂度降一个量级。
二叉树题重点准备层序遍历和最近公共祖先。层序遍历用队列实现,迭代写法比递归更容易写对;很多在线教育题会把层序遍历包装成“按层级输出课程目录”,换汤不换药。
动态规划不要贪多,先把一维DP的常见模型吃透:斐波那契、爬楼梯、打家劫舍、最长递增子序列。做题时先问自己两个问题:状态表示什么?状态怎么转移?这两个问题想清楚,再去看空间能不能压缩成一维滚动数组。
2.2 用一道“合并课程时间段”的完整流程演示做题思路
我拿一道很有代表性的题来说说完整的做题流程。题目大意是:给定一个课程列表,每门课包含开始时间和结束时间,部分课程时间存在重叠,现在需要把重叠的上课时间段合并,返回合并后的区间列表。
听到这道题,先不要急着写代码。第一步是确认输入输出格式,比如时间是整数代表小时,还是字符串代表具体时刻。确认输入是二维数组之后,第二步是脑海里过一遍经典解法:区间合并,先排序,再遍历。接下来就是写代码。
def merge(intervals): if not intervals: return [] intervals.sort(key=lambda x: x[0]) merged = [] cur_start, cur_end = intervals[0] for start, end in intervals[1:]: if start <= cur_end: cur_end = max(cur_end, end) else: merged.append([cur_start, cur_end]) cur_start, cur_end = start, end merged.append([cur_start, cur_end]) return merged写完之后,不要立刻提交。至少花一分钟做三件事:第一,用题目给的示例跑一遍,确认输出一致;第二,构造边界情况,比如空数组、只有一个区间、所有区间都不重叠、所有区间全部重叠;第三,检查时间复杂度,这个解法是排序的O(n log n)加上遍历的O(n),能过绝大多数数据范围。
很多同学笔试时挂在边界条件上,不是不会这个算法。尤其是“当前区间被完全包含在新区间里”的情况,比如已有[1, 5],新来[2, 3],如果不取max(5, 3),合并出来的右边界就错了,而且这种错很隐蔽,小数据量测试都发现不了。我习惯在写完核心逻辑以后,专门写一行注释提醒自己处理右边界,这就是日常练习养成的肌肉记忆。
2.3 编程题拿分策略:先暴力后优化
在线笔试的判分系统只看提交结果,不看过程。这意味着“暴力解法先拿到部分分,再优化到满分”是完全值得采用的策略。很多人一看到最后一道压轴题,脑海里就开始想最优解法,结果想了十五分钟没想出来,代码一个字没写,整道题零分。这种情况我见得太多了。
正确做法是:读题后先评估数据范围。如果n不超过1000,O(n²)的暴力做法完全能通过;如果n到了10的五次方,那就必须奔着O(n log n)或O(n)去。但哪怕最后想不出最优解,也要把暴力版本写出来提交,因为在很多评测规则里,通过部分测试用例是有部分分数的,零分和百分之三十的分差非常大。而且写出暴力版本的过程本身会帮你理解题目细节,往往写着写着就想到了优化方向。
另外,编程题的输入处理非常容易被忽视。有些题目是多组输入,有些是一行数据用逗号分隔,有些是矩阵形式。我见过太多人在LeetCode上写习惯了“函数直接接收参数”的题目,到在线笔试平台被输入输出格式搞懵。提前去了解目标公司用的是哪个在线评测系统,找一套往年题练一练输入输出,能少丢很多冤枉分。
3. 计算机基础高频考点:网络、操作系统、数据库一个都不能少
3.1 操作系统:进程线程、死锁、调度必须拿稳
在线教育笔试的操作系统题,基本锁定在几个最基础的知识点上。进程和线程的区别是必考题,最好能把“进程是资源分配的最小单位,线程是CPU调度的最小单位”这句话理解透,再记住进程间通信的几种方式。死锁的四个必要条件(互斥、占有且等待、不可剥夺、循环等待)是多选题常客,只要出现死锁题,答案基本就是这四个条件的某种排列,备考时把这四个条件背到肌肉记忆的程度。
虚拟内存和页面置换算法也是高频内容,常见考法是给出一个页面访问序列,让你算FIFO和LRU的缺页次数。这种题没有捷径,老老实实画表格推一遍。哪怕是选择题,动手画表也不丢人。调度算法会考作业调度与进程调度的区别,先来先服务、短作业优先、时间片轮转的优缺点,需要能说出它们各自适合什么场景。
复习操作系统时不要深挖底层源码,那是浪费时间。把典型概念之间的对比整理成一张表,比如用户态与内核态、同步与异步、阻塞与非阻塞、并发与并行,笔试选择题的考查本质就是概念辨析,把每对概念的核心差异记清楚就够了。
3.2 计算机网络:三次握手、状态码、HTTPS是三道拦路虎
网络题几乎从不缺席。最经典的三次握手和四次挥手,选择题喜欢换个问法考你,比如“第二次握手时双方处于什么状态”,或者“为什么断开连接需要四次挥手而不是三次”,这些都要理解背后的原因,而不是背流程图。TCP和UDP的区别属于送分题,但不要漏掉“TCP是面向字节流、UDP是面向报文”这个细节。
HTTP协议部分,状态码是选择题的重灾区。200、301、302、304、401、403、404、500、502、503这些要能见到即答。304尤其容易错,它代表“资源未修改,可使用缓存”,不是错误。重定向方面,301是永久重定向,302是临时重定向,在线教育场景里比如课程链接迁移就经常用到这个知识点,出题人很喜欢拿业务场景包装。
HTTPS如果在选择题里出现,大概率会问你TLS握手过程和证书的作用。核心记住:HTTPS并不是在HTTP外面套了一层加密,而是先通过证书验证服务器身份,再用非对称加密协商出对称密钥,之后的数据传输都用对称加密。这一套逻辑能在选择题里回答百分之九十九的问题。至于DNS解析、CDN加速、输入URL后发生了什么,属于送分大题,准备一段标准流程背下来,遇到简答题直接分步骤写。
3.3 数据库:SQL语法之外的隐藏考点
数据库题比大家想象的更看重索引和事务。选择题里最常问的是“以下哪个操作会导致索引失效”,答案通常包括对索引列进行函数运算、隐式类型转换、使用不等于、前导列不在查询条件里。理解了索引的B+树结构,这些失效场景不用背也能推导出来。
事务隔离级别这个考点,四个级别(读未提交、读已提交、可重复读、串行化)要能画出一条递进线,并说出每个级别解决了什么问题、引入了什么问题。主要讨论的是脏读、不可重复读、幻读这三个现象,把它们跟隔离级别对应起来,笔试选择题必拿分。
如果出现手写SQL题,不要急着炫技。先把题读清楚,需要查哪些字段、从哪张表、有没有分组和排序,再一步步写。会考查聚合函数配合GROUP BY的场景,在线教育公司特别喜欢查“每门课的平均完成率”“按周统计的用户增长”这类题目,写的时候注意条件过滤放在WHERE里还是HAVING里,这是最常见的扣分点。
3.4 语言基础:Java与C++的经典陷阱
如果你投后端或客户端,语言基础选择题基本跑不掉。Java阵营常考String、StringBuffer、StringBuilder的区别,HashMap和Hashtable的区别,ArrayList和LinkedList的使用场景,以及异常处理机制里的checked exception和unchecked exception。有一道题出现频率非常高:String用“+”拼接在循环里为什么会慢,答案是String是不可变对象,每次拼接都生成新对象,循环次数多了会产生大量垃圾对象。
C++阵营则更偏向指针和内存,常考指针和引用的区别、栈和堆的区别、构造函数和析构函数的执行顺序、深拷贝与浅拷贝。这里提醒一句:如果你投的是客户端开发岗,多线程同步题几乎是必考,synchronized与volatile的区别、多线程共享变量的可见性问题,这两道题最好提前准备好标准答案。
4. 笔试试卷里那些容易失分的“软性环节”
4.1 简答题与场景题:答到点子上比字数更重要
技术类笔试除了选择题和编程题,偶尔还会有一两道简答题或场景设计题。常见问法比如“某个课程详情页接口响应很慢,如何排查”“请设计一个课程收藏功能的数据表结构”。这类题没有标准答案,但判分的人其实是看你的思路层次。
我的答题套路是“分步骤、说取舍”。以“接口响应慢”为例,不要第一句话就写“用缓存”,而是先拆:第一步,确认慢发生在网络链路还是服务端处理;第二步,看监控指标,CPU、内存、磁盘IO、数据库慢查询;第三步,针对数据库慢查询分析索引和执行计划;第四步,再考虑加缓存、加限流、改异步。每一步说清楚“为什么这么做”,体现的是系统排查能力,而不是背出来的零散知识点。
写SQL表结构的题也一样,要先想清楚核心字段和扩展字段的边界。比如课程收藏表,除了用户ID、课程ID、创建时间,还要不要唯一约束?要不要冗余课程标题?为什么冗余?因为这些字段会影响查询性能,把取舍理由写出来,会比单纯罗列字段得分高很多。
4.2 在线评测系统的使用细节与陷阱
线上笔试跟本地IDE写代码完全是两码事。最大的区别是:你看不到实时报错,只能看到“通过率百分之多少”这个数字。这就需要你提交前做更充分的本地验证。我建议程序写完之后,先把能想到的边界用例全部测一遍,再点击提交。
输入输出的格式问题要格外小心。有些题要求输出结果用空格分隔,有些要求每个结果占一行,多一个空格或换行都可能导致格式错误。如果不确定,可以先用示例输入跑一次,把输出逐字符跟题目示例对照。
还有一个容易忽略的是数据范围和内存限制。某个公司真题里有一道需要申请二维数组的题,数据范围是10的六次方,直接开二维数组直接内存爆炸,正确的做法是用滚动数组或哈希表。做这类题的时候,先看数据规模再决定设计方案的顺序,有时候比算法本身更救命。
4.3 时间分配策略:先做哪道题,后做哪道题
一场在线笔试的总时长通常在九十分钟到一百二十分钟之间,时间非常紧。我的建议是:拿到试卷后,先用两分钟把整张卷子扫一遍,搞清楚有几道选择题、几道编程题、编程题的难易初印象,再决定答题顺序。
常见策略是先快速做完选择题,遇到卡壳超过一分钟的先标记跳过,不要恋战。选择题总共三十分左右,如果在一道题上耗三分钟,编程题的思考时间就被压缩了,非常不划算。编程题建议从签到题开始,先确保第一道题AC,再去做中间题和压轴题。压轴题如果五分钟内完全没有思路,先把暴力版本写上,再去想优化。最后如果还有剩余时间,回头处理跳过的选择题。
时间分配的基本原则是“宁可不完美,不能不交卷”。笔试平台判分只看提交结果,一道题写得再完美,不提交就是零分。我见过有人压轴题想到一种很复杂的优化,结果没时间写完,前面的题也时间不够粗心错了,最后总成绩惨不忍睹。稳扎稳打、保证每道题都有得分,才是校招笔试的生存之道。
5. 一个月备考计划:从摸底到复盘的完整路径
5.1 四周复习节奏表
我帮不少同学规划过校招备考路径,最终稳定执行的方案是四周制。第一周是“摸底和基础回流”,找一家目标公司往年的真题做一次限时模拟,不用管分数,关键是找出自己的薄弱板块,同时把数据结构的基础内容过一遍:数组、链表、栈、队列、哈希表、二叉树。第二周进入“算法专项训练”,按专题刷题:双指针、滑动窗口、区间合并、二叉树遍历、基础DP,每天至少做中等题五道。
第三周开始“计算机基础八股和语言强化”,操作系统、网络、数据库三张思维导图铺开,每两天过一门,配合选择题专项练习。第四周回到“整套真题模拟”,严格按考试时间做完整试卷,每周模拟不少于三次,每次模拟完都要完整复盘。四周下来,做题量不需要刻意追求一千道,两百道精刷加两套完整真题,已经能覆盖绝大多数考点。
5.2 错题复盘模板
刷题不等于会题,复盘才是刷题的核心。我建议每位准备笔试的同学都建一个自己的错题档,不用很复杂,一个表格就行,但每道错题都要填五列:题目描述、考点分类、错误原因、正确思路、一句话总结。错误原因要写具体,是数据范围没看到,还是边界条件漏了,或者是状态转移方程推错了,不要笼统写一句“题目不会”。一句话总结只允许写一句,逼自己提炼出最核心的规律。
坚持三周之后回看错题档,你会发现高频错误往往集中在某几个固定模式上。比如有些人的区间题永远错在边界开闭,有些人的DP永远忘记初始化。找到这个模式,比再做五十道新题更有效。定期的错题回看安排在每周末,把本周错题档里的题目重新在纸上写一遍思路,写不出来就标记为“未消化”,下周优先重做。
5.3 刷题过程中的三个常见误区
第一个误区是只刷难题不刷中等题。很多人一上来就直奔难偏怪题,觉得这样进步快,结果基础知识没夯实,考场上一道看似简单的签到题反而因为手生写不出来。校招笔试的难度主体是中等偏下,把中等题做到又快又准,远比会做三道难题有意义。
第二个误区是背题不推理。背某个题目的代码模板,遇到换皮题就抓瞎。算法题的核心是建模能力:把文字描述抽象成数据结构,把问题转化成已知模型。备考时要刻意练习这种转化,每次读完题先不急着写代码,先口述一遍“这道题可以用什么数据结构解决,为什么”。
第三个误区是忽视代码风格。在线笔试平台虽然不考察命名规范,但代码质量会影响你的做题效率,变量命名为a、b、c,写到后面自己都分不清哪个是哪个,逻辑错了都难定位。考试时用有意义的变量名,哪怕只是begin、end这样的单词,也能让思路清晰很多。
最后再分享一点个人经验
看了这么多年的校招笔试和候选人表现,我最大的体会是:筛选人的核心从来不是谁刷的题多,而是遇到没见过的问题时,能不能有一整套稳定可复用的拆解流程。所以每次笔试结束,不要只看分数,先把每个题型的耗时、卡壳点、写错的边界条件记下来,积累个二十道这样的记录之后,你会发现自己在考场上越来越稳。
另外一个小技巧是:考前把常考的复杂度总结背下来,比如排序算法的平均复杂度和稳定性、HashMap常见操作的时间复杂度、二叉树的遍历复杂度。这些内容不需要高频刷题来巩固,但考场上能帮你快速判断自己的解法是否可行,省下大量试错的时间。祝准备校招的各位都能顺利拿到心仪的offer。