
1. 这份笔试卷考的不只是知识点我手上这份《猿辅导2017校招笔试题卷一》在很多人眼里可能只是一份过期资料。但如果你认真把题目过一遍会发现它的考察逻辑和今天大多数互联网公司的校招笔试题高度一致基础扎实不扎实代码能不能在有限时间内写出来碰到没见过的题有多快找到思路。说白了这份卷子是一个浓缩的“能力切片”能从中读出一家公司对工程师的基本预期。当年猿辅导正值在线教育高速扩张阶段需要大量能直接上手写业务代码、又能扛住高并发场景的技术人员。所以它的笔试题并不是单纯堆难偏怪题而是覆盖了数据结构、算法、计算机网络、操作系统、概率统计和一两道有区分度的编程题。这种结构在今天看来依然是主流先快速筛掉基础不牢的人再通过算法题考察思维深度和代码能力。我也见过不少准备校招的同学把大量时间花在刷LeetCode上却忽略了基础知识的系统性复习。结果笔试时选择题连错一片编程题也没做出几道。原因很简单校招笔试不是单项竞技而是一场综合考核。你面对的是一个需要合理分配注意力和时间的完整场景。这篇文章我就以这份卷子的典型结构为例把每个模块怎么准备、怎么答题、有哪些坑一条条拆给你看。2. 选择题里的高频考点拆解2.1 数据结构链表、二叉树、哈希表背后的思维这类卷子选择题的第一梯队几乎必然有数据结构和算法基础题。链表和数组的区别、二叉树的前中后序遍历、哈希表的冲突解决方式是出现频率最高的三块。很多同学觉得这些都是简单题不值得多花时间但恰恰是这些“简单题”最容易暴露理解不透的问题。比如“数组和链表的区别”这道经典的不能再经典的题对应聘者而言不是背出区别就完事。面试官真正想看到的是你懂不懂它们各自适用的场景。数组适合随机访问和缓存友好的顺序遍历链表适合频繁插入删除但无法高效随机访问。落到工程里一个日志系统要顺序写入和倒序查看用什么结构更合适答案是数组加下标因为内存连续、遍历快而一个LRU缓存要频繁把某个节点移到头部那就得靠哈希表加双向链表。你能把这种场景对应关系说出来这道题才算真正拿满分。二叉树遍历题在试卷里通常是给一个树的形状求某种遍历顺序或者反过来给前序中序求后序。这里有个特别实用的心得给定前序和中序重建二叉树的核心规律是“前序的第一个节点是根在中序里找到它就能把左右子树分开”。这个规律手动做题很好用写代码时更要熟练。建议准备笔试前把二叉树的递归遍历和非递归遍历都默写一遍尤其是非递归的后序遍历因为它最容易在考场上卡壳。哈希表这块常见考法有哈希函数构造、冲突处理方法链地址法、开放定址法、再哈希法等和装载因子对性能的影响。笔试考卷里往往只问概念但面试环节会继续追问“为什么Java 8里HashMap在链表长度超过8时会转成红黑树”答得上这一层的同学会直接拉开差距。我的建议是复习数据结构时不要只背结论要把“为什么”一并弄明白因为笔试之后还有面试每一个选择题都可能成为面试追问的引子。2.2 计算机网络与操作系统容易被忽视的分值很多人备战编程笔试时基本放弃网络和操作系统觉得“反正编程题才是大头”。但实际上一份卷子里选择题总共就那么几十道网络和系统各占几道每一道都是你丢不起的分。尤其是当大家编程题水平都差不多时决定你能不能进面试的可能就是这几道基础题。计算机网络的选择题集中在TCP三次握手、四次挥手、TCP与UDP的区别、HTTP状态码、DNS解析过程上。一个高频考法是给你一个状态码让你判断含义。比如“301和302有什么区别”301是永久重定向302是临时重定向。再深一点的追问是“POST和GET分别对应哪种重定向”这里就有坑很多浏览器对POST的301和302处理方式不同部分浏览器会把POST变成GET丢失请求体。虽然2017年的卷子未必考到这个深度但这类“知识点背后的实际行为”恰恰是区分普通候选人和有工程经验候选人的地方。操作系统题则集中在进程与线程、死锁的四个必要条件、虚拟内存与分页、进程间通信方式上。有个特别经典的题“进程和线程区别是什么”要答全得从资源分配和调度的基本单位说起还要提一嘴线程共享进程的地址空间、进程之间相互隔离。如果你想答得更有层次可以补充一个场景多线程编程时为什么通常会引发现存量竞争因为线程共享堆内存光是Java里new一个对象都可能产生并发问题。这种结合实践的理解比死记硬背十个区别更迷人。还有一个容易被忽略的点操作系统里的调度算法。选择题可能会出现“以下哪个调度算法会导致饥饿”短作业优先SJF可能会让长作业长期得不到CPU。这是道典型概念题花十分钟把常见调度算法的优缺点过一遍基本就不会丢分。2.3 概率统计与逻辑题算法工程师的基本功在技术岗笔试卷里概率题不是用来凑数的。它考察的是你对随机事件的理解建模能力而这种能力在推荐系统、AB实验、风控模型这类工程里天天要用。猿辅导从2017年开始就布局大班课和小班课业务用户量庞大推荐策略和转化率分析都是核心问题笔试卷里出现概率题完全不意外。常见的概率题有几种类型。一种是“袋子里有红球蓝球取球取到某种颜色概率是多少”这种题考条件概率和贝叶斯公式手动算一通就能出结果。另一种是“两个随机变量独立同分布求某个事件概率”这种题考验的是分布函数的计算能力。还有一种是期望题比如“不断抛硬币直到出现连续两次正面求抛掷次数的期望”这种题看起来简单但特别容易错。做概率题时我有一个小技巧先判断事件是否独立再决定用乘法公式还是全概率公式。很多同学丢分不是不会算而是漏掉了“需要分情况讨论”的前提。比如要求“至少有一人命中”的概率正确的第一步是先算“全都未命中”的补集概率。养成这个“先找补集、再算条件概率”的习惯做选择题会快很多。逻辑题则更多是考察你在信息不完整的情况下如何推理。偶尔会出现类似“甲乙丙丁四个人分别来自四个城市每人只说一句真话判断谁来自哪里”的题目。这种题没什么高深理论但要求你耐心列条件做排除。笔试试卷里遇到它值得高兴因为它是保分题只要你控制好时间一步步推理一定能做出来。3. 编程题的完整拆解与实战思路3.1 从一道典型的字符串题看解题流程编程题是校招笔试的核心区分项。我以一份这类卷子里最常见的一道题——求字符串里不含重复字符的最长子串长度——为例完整走一遍解题流程。需要注意这只是代表题不是原卷原题但解题思路可以完全复用。拿到题目后不要急着写代码。第一步是确认输入输出格式和边界条件字符串为空时返回什么字符串长度为1时返回什么字符集是仅包含小写字母还是可能包含任意ASCII字符这些信息直接决定你用数组还是哈希表做标记。第二步是分析算法复杂度。暴力解法是枚举所有子串并检查是否含重复字符时间复杂度O(n^2)空间复杂度O(1)。这种解法在笔试里通常只能通过少量测试用例。优化的思路是滑动窗口用两个指针left和right维护一个无重复字符的窗口右侧指针不断向右移动遇到重复字符时左侧指针移到重复字符上一次出现位置的下一个位置在整个过程中记录窗口最大长度。这样时间复杂度降为O(n)空间复杂度O(字符集大小)。第三步才是动手写代码。写的时候要注意几个细节重复字符的记录要存最近一次出现位置的下标这样left可以直接跳到那个下标加1的位置而不是一个一个挪更新最大长度的时候要放在每次right移动后而不是只在遇到重复时更新。这两个细节是大多数人写这道题出错的地方。做笔试题的时候别指望一上来就写出完美代码。我更习惯先写一个“够用的版本”确保核心逻辑正确再根据剩余时间做优化。如果时间不够O(n^2)的暴力版也能拿部分分总比交白卷强。3.2 从暴力解法到最优解法的演进同样一道题不同解法之间的差距就像从骑车到开车的差距。我在给应届生做模拟面试的时候最常看到的情况是知道要用滑动窗口但讲不出为什么滑动窗口是正确的。这里要用到单调性对于一个无重复字符的子串它任意一个子串也必然无重复字符。这就保证了窗口左侧指针向右移动时不会漏掉更优的解。我把解法的演进过程写出来方便你照着这个思路做其他题。暴力法枚举所有i到j的子串用Set去重判断记录最长长度。复杂度高但容易想清楚。优化法固定左指针向右延伸右指针当出现重复时左指针右移一位重复这一过程。这本质上还是O(n^2)的双重循环但相比枚举所有子串已经能少很多无效计算。滑动窗口右指针不断向右移动一旦发现当前字符已经在窗口内就把左指针直接跳到当前字符上一次出现位置的下一个位置。每个字符最多被左右指针各访问一次复杂度是稳定的O(n)。这三步演进展示的核心能力是“对暴力解进行剪枝优化的意识”。面试官在看你代码的时候看的正是你有没有这种意识。即使第一版没写出来最优解你能在代码里体现“我正在把重复计算去掉”的过程也是加分项。这里给你一个可以直接套用的模板如果题目有“连续子串”的约束优先想滑动窗口如果题目是“找两个有序数组中位数”这种优先想二分如果题目是“从起点到终点最小代价”优先想BFS或者DP。把常见题型的通用解法整理成模板考场上就相当于带着小抄入场。3.3 代码实现与边界条件处理光有思路不落地等于零。下面给一个完整可运行的最长不重复子串长度的代码示例语言用Java因为校招笔试系统里Java和C是接受度最高的两个选择。public int lengthOfLongestSubstring(String s) { if (s null || s.length() 0) { return 0; } MapCharacter, Integer lastIndexMap new HashMap(); int left 0; int maxLen 0; for (int right 0; right s.length(); right) { char c s.charAt(right); if (lastIndexMap.containsKey(c)) { // 这里用max防止left因为重复字符反而往回跳 left Math.max(left, lastIndexMap.get(c) 1); } lastIndexMap.put(c, right); maxLen Math.max(maxLen, right - left 1); } return maxLen; }这里有个特别容易翻车的点当窗口收缩时为什么用Math.max(left, lastIndexMap.get(c) 1)而不是直接令left lastIndexMap.get(c) 1原因在于left只能向右移动不能回退。考虑字符串“abba”第一次遇到第二个b时left跳到2接着遇到第二个a时a上次出现在0如果直接left1就回到了旧位置滑动窗口就失去了“不回头”的保证。这个坑我在模拟面试里看到至少一半的人踩过。写完代码后要做两件事第一用几个典型用例在脑子里跑一遍逻辑比如空串、单字符、全相同字符、全不同字符、含数字和空格等第二检查复杂度是否满足题目约束通常数据量在10^5级别时O(nlogn)是可接受的但如果数据量到10^6O(nlogn)就很悬了。这里再额外补充一个笔试时非常有用的实操心得大多数在线笔试题平台都支持你读入测试用例、打印中间值做本地调试。如果平台允许在提交前先自己构造几个边界用例测一下。如果平台不支持本地调试那就更要在写代码时把边界条件写在最前面然后再写主逻辑。这么做看起来费时间实际上能帮你避免因为简单的空指针或越界问题而整道题失败。4. 如何像高手一样备战校招笔试4.1 倒推式复习计划聊完了题目本身再聊一个更现实的问题拿到一份笔试题卷你该从哪里开始复习我见过太多人一上来就闷头刷题刷了一个月发现选择题还是错一半编程题也没显著提升。原因在于复习没有目标刷题没有策略。我自己的建议是做倒推式复习。先看目标公司的真题或者同类公司的笔试题把考察的知识点列出来然后对照自己的掌握程度做一个优先级排序最后按优先级分配时间。就拿这份典型的笔试卷来说知识点可以分成三档第一档必须滚瓜烂熟数据结构与算法中的链表、栈与队列、二叉树、排序与搜索、哈希表编程题中的字符串处理、数组问题、简单动态规划。这些是每一场笔试都会出现的核心考点。第二档需要理解原理并能快速推理计算机网络中的TCP/IP协议、HTTP协议操作系统中的进程线程、内存管理概率统计中的期望、条件概率。这类题数量不多但性价比极高花一个晚上复习就能多拿好几道选择题的分。第三档有余力再深入复杂动态规划、图论算法、海量数据与设计题。这部分是区分头部候选人的内容适合时间充裕、目标明确冲击高分的人。制定计划时我建议把一周分成三段前四天按知识点专题复习和刷题中间两天做整套笔试题模拟最后一天集中整理错题和薄弱点。用这种“专题套题复盘”的循环一个月下来效果远好于每天漫无目的地刷两三道题。4.2 刷题的正确姿势不是数量而是总结很多人把刷题数量当作衡量标准一天刷十道就觉得今天没白过。但你问他这道题考的是哪个知识点还有没有更优的解法代码哪里容易写错大概率答不上来。这种刷题方式就是自我感动对提升笔试成绩帮助不大。我比较推荐的三步刷题法是先独立思考十分钟没思路就看题解看完题解后合上答案自己写一遍代码最后在笔记里总结这道题的解法和适用条件。这个过程比单纯做题多花一倍时间但记忆保持率也高好几倍。另外非常重要的一点是一定要按专题刷题不要随机刷题。比如这周只看滑动窗口和前缀和下周只看二分查找和双指针。按专题刷你才能真正理解这类题型的共性解法考场上看到新题才能快速归类。我碰到很多同学单聊每一道题他都见过但把题目改头换面一下就不会了。这就是因为没有总结题型只记住了题目本身。4.3 笔试现场的策略与心态笔试现场和LeetCode刷题最大的不同是有时间限制、有心理压力、还有多个题目并行。策略错了会做的题也没时间做。我给你的现场时间分配建议是拿到卷子后先花两分钟把所有题目扫一遍快速判断哪些题有把握、哪些题需要多花时间选择题部分控制在一分钟以内一道遇到卡了超过三分钟的题直接标记跳过最后有时间再回来检查编程题从最有把握的那道开始做先保证至少有一道题是完全AC的再去做难度更高的题。这个“先易后难”的策略特别适合校招笔试因为大多数公司的笔试不是按题目顺序判分的而是按通过的测试用例数量算分。你把一道简单题拿满分胜过三道题都写了暴力解但全不过。再聊一点心理层面的东西。编程题卡住的时候很多人会陷入一种“必须马上想出来”的焦虑状态结果越焦虑思路越乱。我的建议是如果一道题卡了十五分钟还没思路先停笔深呼吸把题目重新读一遍然后把能想到的暴力解法在草稿纸上写下来。很多时候写着写着就会想到优化的切入点了。如果实在做不出来果断放弃去做其他题不要在一道题上赌上整场笔试。5. 卷面之外吃透笔试题比你想象中更有价值5.1 从一次笔试中挖出你的能力地图很多同学笔试结束后就彻底放松觉得卷子交了就跟我没关系了。但以我带人的经验来看笔试后的复盘价值甚至超过笔试本身。你交上去的卷子就是一张精准的“能力地图”越做越顺的板块是你的舒适区卡壳的地方是马上需要补的短板。具体怎么做呢首先把所有错题和蒙对的题整理一遍按知识点归类算出每个板块的正确率然后找出正确率最低的三个板块作为接下来一周的复习重点最后把编程题里没写出来或者没写最优解的题重新做一遍直到能在不看题解的情况下独立AC。这个过程看上去很枯燥但它比盲目刷题高效得多。我见过一个特别夸张但有效的做法有个同学把每一次笔试的错题都整理成一份带解析的错题集笔试结束当天晚上就对答案第二天一早就把错题重新做一遍。一个月后他的笔试题水平肉眼可见地上升最终拿了好几个大厂的offer。这个习惯一直延续到他工作后。5.2 笔试中的思考过程是面试最好的谈资还有一个容易被忽略的维度笔试时的思考过程本身就是面试时可以展开的话题。现在很多公司的面试官会调出你的笔试记录问“你当时这道题是怎么想的”“为什么选择这个解法”“现在再看这道题有没有更好的方案”如果你只记得题目的一个零散解法解释不清思路面试官会怀疑你的答案是不是抄的。所以每做完一套笔试题我都会建议你在复盘时顺便写下“思路稿”这道题我乍一看是什么感觉、我先尝试了什么方法、后来为什么换方案、如果重做会在哪里改进。这个稿子既是给自己的复习材料也是面试时的答题提纲。面试官问起来你能清晰地说出“我当时先想到暴力解然后发现暴力解会有重复计算就优化成滑动窗口”这比说“我写过用的滑动窗口”要有说服力得多。我还想提醒一点笔试题里暴露的问题很可能在你入职后以另一种方式出现。比如你选择题不会做进程与线程的关系大概率是对并发编程理解不到位你编程题没处理好空输入大概率是写代码时习惯不关注边界条件。笔试题的考点设计本身就是从工程实践里提炼出来的。把笔试题当作一次体检早发现问题早补是对自己负责。6. 写在最后笔试没有捷径但复盘有校招笔试确实没有捷径可走知识点就是那些题目形态千变万化但核心能力是不变的基础扎实、思路清晰、代码熟练、时间管理合理。如果你认真按这篇文章的思路去拆解一份笔试题再对照自己的薄弱点做针对性的复习我敢说你下一次笔试的成绩一定会比上一次好上不少。最后再分享一个小技巧我每次做完整套笔试题后都会把最有价值的一道错题拍下来存在手机里在地铁上、排队时反复刷几遍。不要小看碎片时间的叠加效应一个月下来这些零散时间足够你把最薄弱的知识点彻底啃下来。笔试备战不是一场冲刺跑而是一场有节奏的马拉松希望你能稳住节奏跑完全程。