搜狐2017校招研发工程师模拟笔试题(二)复盘:考点与解题思路 先做个坦白我刚入行那年第一次认认真真刷题准备校招用的就是搜狐2017校招研发工程师模拟笔试题二。当时没觉得这套题多特别单纯是“多刷一道是一道”。后来工作了几年回头再看才意识到这套题基本把互联网研发岗笔试的地基全踩了一遍。数据结构、C语言、网络、操作系统、数据库一个没落而且考法不偏不怪全是面试官真正在意的东西。所以今天想认真复盘一下这套模拟笔试题二不是给你贴一份参考答案就完事而是把你放在考场上告诉你每道题在考什么、为什么这么考、解题的思考路径是什么、以及哪些地方是历届考生最容易掉坑的。不管你是明年才参加校招的在校生还是正在紧锣密鼓刷题的应届生这篇文章都能让你对“互联网公司研发工程师笔试到底考什么”这件事有一个完整的认知框架。1. 2017年的题放到今天到底还有没有参考价值先说结论参考价值非常大甚至比某些今年的新题还大。原因很简单——校招笔试的考察范围本质上十几年没变过。语言基础、数据结构、算法、计算机网络、操作系统、数据库这些是计算机专业的核心知识也是研发工程师日常开发的地基。地基不会一年换一套所以2017年的题目放在2025年考点照样是考点。举个例子这套模拟笔试题二里有涉及二叉树遍历、进程线程区别、TCP三次握手这类题你现在随便打开一家公司的校招笔试题库照样能看到类似影子。甚至很多公司出题时会直接复用或者改编老题因为出题人觉得一道题能有效区分候选人的基础扎实度那就值得反复用。再者你刷老题有一个额外的好处你能感知到出题人的“审美”。搜狐所在的互联网圈笔试题目向来中规中矩、偏重基础不搞偏题怪题。刷完这套题你基本就能摸清这类公司筛选候选人的逻辑——基础扎实、算法过关、思维清晰就这三板斧。当然有一点要提醒老题里的技术栈会有时代痕迹比如C语言相关题目比例较高而现在很多岗位更偏向Java或Go但这不是你可以跳过C语言题的理由。笔试考C语言不是为了让你以后用C写业务而是考察你对内存、指针、底层运行机制的理解。这些能力放哪个语言都一样。2. 整张卷子考了什么考点地图与命题逻辑拆解2.1 互联网公司研发岗笔试的统一底牌刷题刷多了你会发现不管哪家公司研发岗笔试题基本逃不出这几块计算机基础知识C语言为主、数据结构与算法、计算机网络、操作系统、数据库外加一两道逻辑题或编程题。这个结构不是拍脑袋定的它对应的是一个研发工程师日常工作中真正需要的基本功。计算机基础决定你能否写出靠谱的代码数据结构和算法决定你的代码能否高效运行网络和操作系统决定你能否在分布式环境下定位问题数据库则直接关联业务开发中的存储和查询设计。每家公司都希望招进来的人不用从头补基础所以笔试就是在最短时间内筛出基础达标的人。这套搜狐2017校招研发工程师模拟笔试题二也不例外。它覆盖了上述全部核心板块题目难度呈梯度分布既有送分题也有拉开差距的题而且部分题目设计了“连环坑”——比如一道关于指针的题表面考指针和数组的关系实际上还掺了运算符优先级、内存布局两个考点。2.2 模拟笔试题二的考点权重与分值分布按记忆给这套卷子做个知识点的权重划分大致是这样的考察板块典型考点题量占比难度星级C语言与内存指针、数组、结构体、运算符优先级25%三星数据结构与算法栈、队列、二叉树、查找排序、动态规划30%四星计算机网络TCP/IP、HTTP、DNS、三次握手15%三星操作系统进程线程、死锁、内存管理、调度算法15%三星数据库SQL语法、索引、事务隔离级别、范式10%两星逻辑与综合智力题、场景设计题5%三星注意这里的数据结构和算法占比最高这反映了搜狐乃至整个互联网行业对算法能力的重视。笔试环节算法题不达标基本直接淘汰因为算法题是最难靠死记硬背蒙混过关的部分。另一个值得注意的点是这套卷子里C语言题量大且细说明当时的出题人非常看重候选人对底层机制的理解。现在不少公司笔试改成了语言自选但底层原理的考察并没有消失只是换了个语言外壳继续考。所以看到C语言题不要划走把思路理顺了对答Java题、Go题同样有用。3. 高频考点复盘六大方向逐个拆给你看3.1 C语言与内存管理笔试的第一道硬门槛C语言题在校招笔试里是最两极分化的板块。基础扎实的人觉得是送分题基础薄弱的人连题目在问什么都看不懂。这套模拟笔试题二里的C语言题集中考了三块指针、数组和内存布局。先说指针。别小看指针指针题目是区分“背过八股文”和“真正理解内存”的试金石。常见的考法有几种指针加减法的实际效果、指针与数组名的区别、多级指针的概念辨析、指针作为函数参数时的传递方式。这里最经典的坑是“数组名和指向数组首元素的指针是否完全等价”。结论是在大多数表达式中二者可以互换使用但数组名不是变量不能做自增自减而且对数组名和指针分别取sizeof结果是完全不同的——一个是整个数组的大小一个是指针本身的大小。再说内存布局。笔试喜欢考栈区和堆区的区别、局部变量和全局变量的生命周期、static关键字的作用。这里有一个高频考点函数内定义的局部数组返回后能不能继续使用答案是不能因为它在栈上函数返回后栈帧就被释放了继续访问属于未定义行为。但如果你用static修饰或者用malloc在堆上分配返回后就可以用。关于运算符优先级2017年的题目也很偏爱。这个知识点现在很多笔试仍然在考因为它在实际工程里真的会坑人。比如*p到底先取指针指向的值还是先移动指针答案是先取*p然后指针加一这是因为后缀的优先级高于解引用*。这种题一旦做错说明代码阅读能力不过关后面编程题也会受影响。3.2 数据结构与算法决定你能否进面试的分水岭数据结构和算法是校招笔试的C位也是拉分最关键的部分。这套模拟笔试题二里涉及的考点非常多栈与队列的基本特性及应用场景、二叉树的各种遍历方式、排序算法的稳定性与复杂度、二分查找的边界条件、简单动态规划问题。下面挑几个重点展开讲。栈和队列的考点集中在“先进后出”和“先进先出”的应用场景辨析。面试官很喜欢问“用栈实现队列”或“用队列实现栈”这个题看起来简单实际写起来要考虑元素转移的时机很多人一紧张就写错。核心思路是用两个栈入队时直接压入栈A出队时若栈B为空把栈A的元素全部弹出并压入栈B再从栈B弹出这样就能保证先进来的元素在栈B的栈顶。二叉树是必考中的必考。层序遍历、前中后序遍历、求二叉树深度、判断平衡二叉树这些都是基本盘。当时卷子里有一道二叉树层序遍历相关的编程题要求按层输出节点并区分每一层。这个题的难点在于如何知道当前层结束的位置——常见的解法是用队列配合一个层节点数的计数变量。具体做法是每次循环开始前记录当前队列的长度这个长度就是当前层的节点数然后弹出这个数量的节点并处理它们的子节点这样就能完整区分每一层。排序算法这块笔试不一定会让你手写快排但一定会考概念哪些排序是稳定的哪些是不稳定的快排的平均复杂度和最坏复杂度分别是多少什么时候该用堆排序。这里有个记忆技巧稳定的排序算法有冒泡、插入、归并、基数不稳定的有快排、选择、堆排序、希尔。至于复杂度绝大多数情况背这张表就够了排序算法平均时间复杂度最坏时间复杂度空间复杂度稳定性冒泡O(n²)O(n²)O(1)稳定插入O(n²)O(n²)O(1)稳定快排O(n log n)O(n²)O(log n)不稳定归并O(n log n)O(n log n)O(n)稳定堆排序O(n log n)O(n log n)O(1)不稳定二分查找也是高频考点但我发现很多人不是不会写二分而是不会写对。在2017年的笔试题里二分查找的变体题很常见比如找旋转数组的最小值、找第一个大于等于目标值的位置。这些题的共同难点是边界条件。给你一个我当时踩过坑之后总结的口诀循环条件是left right收缩时left mid 1或right mid - 1这样不容易死循环。如果你希望找左边界收缩右边界时用right mid找右边界时收缩左边界用left mid 1。注意这两个套路对应的循环条件要改成left right否则会因为边界处理不当跑出正确结果但实际在靠运气。动态规划的题出现频率也很高。常见的有斐波那契数列改进版、爬楼梯、打家劫舍、最长回文子串、背包问题。动态规划的核心就三步定义状态、找状态转移方程、确定初始化和遍历顺序。很多同学卡在“定义状态”这步其实只要多做题很容易培养出感觉。以最长回文子串为例状态可以定义为dp[i][j]表示子串s[i:j]是否是回文转移方程是dp[i][j] (s[i] s[j]) (j - i 3 || dp[i1][j-1])。其中j - i 3是核心细节它处理了长度为1和2的子串边界情况。这个细节如果想不到代码必错。3.3 计算机网络三个逃不掉的经典模型计算机网络在研发岗笔试中占的比重不算最高但几乎必考而且考来考去就那几个点TCP三次握手和四次挥手、TCP和UDP的区别、HTTP协议的状态码和请求方法、DNS解析流程。TCP三次握手是默写题但2017年的题里考得很细不是让你把三个步骤写出来而是问你“第三次握手失败会发生什么”或者“为什么需要三次而不是两次”。要答好这样的题不能只背流程要理解握手的本质——确认双方的收发能力都正常。第一次握手客户端发送SYN服务端确认客户端发送能力正常第二次握手服务端发送SYNACK客户端确认服务端收发能力都正常第三次握手客户端发送ACK服务端确认客户端接收能力正常。所以为什么是三次因为两次的话服务端无法确认客户端的接收能力是否正常。HTTP状态码也是一个非常实用的考点。笔试喜欢考的是304、403、404、500、502、503这些。这里说一下容易被忽略的304它表示“Not Modified”用于协商缓存。当浏览器再次请求资源时会带上上次响应中的ETag或Last-Modified信息服务器经过比对如果资源没有变化就返回304告诉浏览器直接使用本地缓存。这个机制对网站性能优化非常重要校招面试中也经常会顺着这个问题聊到缓存策略。TCP和UDP的区别这道题看似简单但想拿满分别漏点。可以从连接性、可靠性、传输方式、头部开销、适用场景五个维度回答。补充一个容易忘记的点TCP是面向字节流的UDP是面向报文的。前者的含义是没有明确的消息边界传输数据可能粘包后者则每个数据报都独立各次读取不会互相干扰。这样答出来才算全面。3.4 操作系统进程线程、死锁、内存一轮扫清操作系统板块在笔试里一般考这些进程和线程的区别、死锁产生的必要条件、进程调度算法、虚拟内存和分页。这套模拟笔试题二里的操作系统题不偏但陷阱不少。进程和线程区别是绝对高频。2017年爱考2025年还在考。答题时从资源分配、调度开销、通信方式、稳定性四个角度切入进程是资源分配的基本单位线程是CPU调度的基本单位进程间相互独立一个崩溃不影响另一个而同进程的多个线程共享地址空间一个线程出问题可能导致整个进程挂掉进程通信需要借助IPC机制线程间可以直接读写共享变量进程创建开销远大于线程。死锁问题是另一个必考点。死锁产生的四个必要条件互斥条件、请求与保持条件、不可剥夺条件、循环等待条件。重中之重是循环等待条件因为破坏它是最常见的死锁预防手段比如按固定顺序加锁。做题时最经典的题目是“系统有3个进程每个进程需要5台打印机系统至少需要多少台打印机才能保证不发生死锁”。这个题的标准解法是每个进程已分配4台打印机时系统再留1台空闲的这样任意一个进程拿到第5台后就能运行完运行完释放全部打印机后续进程依次完成。所以答案是13台。在题目里遇到这类资源分配题记住这个通用思路最坏情况下每个进程差一个资源系统留一个备用即可。调度算法也常考。先来先服务、短作业优先、时间片轮转、优先级调度这四种是必须掌握的。笔试喜欢让你算出平均等待时间或平均周转时间。计算时注意短作业优先的平均等待时间是最优的但可能有“饥饿”问题时间片轮转则适合交互式系统。还有一个很多人忽略的概念——响应时间它是衡量交互式系统的重要指标轮转调度在这方面很友好。3.5 数据库与SQL最容易被忽略的得分点数据库在研发岗笔试中占分不大但往往是最好拿的分因为它规律性强。狐2017年模拟笔试题二里的数据库题主要涉及SQL编写、索引原理、事务的ACID特性和隔离级别。SQL题一般让你手写查询或者给一个查询让你判断是否正确。最常考的有多表联查、分组统计、子查询、去重。这里提醒一个高频错误点WHERE和HAVING的区别。WHERE在分组前过滤不能使用聚合函数HAVING在分组后过滤可以使用COUNT、SUM等聚合函数。你要是把HAVING写错成WHERE在有些数据库中会直接报语法错误就算不报错逻辑也完全不对。索引原理重点考聚簇索引与非聚簇索引的区别以及最左前缀原则。简单讲聚簇索引的表数据行和索引存的是同一份数据也就是说表记录的物理存储顺序和索引顺序一致非聚簇索引则索引和数据分开存索引的叶子节点只存了指向数据的指针。最左前缀原则是联合索引的核心比如建立了(a,b,c)联合索引那么a、a,b、a,b,c这三组条件都可以命中索引但b,c或a,c这种跳过最左列的查询索引是不生效的。做题时判断是否会走索引就看查询条件里有没有包含联合索引的最左字段。事务隔离级别也是老面孔重点在于理解四个级别的区别以及分别能解决什么问题。读未提交允许脏读读已提交避免脏读但可能出现不可重复读可重复读避免不可重复读但可能出现幻读在最严格的序列化级别下所有问题都能避免。MySQL的InnoDB引擎默认是可重复读级别这一点也经常被拿来单独提问。3.6 编程题与逻辑题大题拿分的建模思路编程题是重头戏也是很多考生最紧张的部分。这套模拟笔试题二里的编程题不是最难的但非常考验现场建模能力。做编程题的流程应该是读题、抽象、设计算法、写代码、测试边界。很多人直接跳过抽象设计上来就码代码这是大忌。比如有一道题让我印象深刻已知一个有序数组里面存在重复元素要求找出某个目标值第一次出现的位置。这道题表面是查找问题实际上考的是二分查找的变体。我刚入行时遇到这种题会直接调API但笔试不让你调。正确的解法是二分查找时如果中间值等于目标值不急着返回而是把右边界收缩到中间值的位置继续向左找直到左边界越界。这里最难想明白的点是为什么等于目标值还要继续往左因为你要找的是第一次出现的位置中间值左边可能还有一样的值。逻辑题也偶尔出现在这套卷子里比如等量代换、真假话推理、最优策略问题。逻辑题的核心是“不跳步”把条件用符号或表格逐条列出来很多题看起来绕列完表格就通了。我一般会把条件写成布尔表达式逐个试这样不容易漏条件。4. 真题逐题复盘拿三道代表性题目演示解题全过程4.1 算法题二叉树层序遍历的变形当时这套模拟笔试题二里有道编程题要求按“之字形”顺序打印二叉树也就是第一行从左到右第二行从右到左第三行再从左到右交替打印。这道题本质是层序遍历的变形但坑不少。解题思路分三步。第一步用队列进行标准层序遍历同时记录每一层的节点数。第二步维护一个布尔变量leftToRight表示当前层是否从左往右打印。第三步当层序遍历到某一层时把该层节点的值先存到一个临时数组里如果当前层需要从右往左打印就把这个临时数组反转后再加入结果集。这里有一个关键细节反转数组虽然直观但会带来O(n)的额外开销。如果面试官追问优化方案可以改为用双端队列或双向链表来维护每一层的值——从左往右时尾插从右往左时头插。我当时在笔试题里写的就是伪代码因为笔试时间有限先用伪代码把逻辑理清楚之后再补完整实现这个策略在时间紧张时很实用。完整参考代码C风格vectorvectorint zigzagLevelOrder(TreeNode* root) { vectorvectorint result; if (root nullptr) return result; queueTreeNode* q; q.push(root); bool leftToRight true; while (!q.empty()) { int size q.size(); vectorint level(size); for (int i 0; i size; i) { TreeNode* node q.front(); q.pop(); int index leftToRight ? i : size - 1 - i; level[index] node-val; if (node-left) q.push(node-left); if (node-right) q.push(node-right); } result.push_back(level); leftToRight !leftToRight; } return result; }这种做法的一个技巧是不先存数组再反转而是根据leftToRight直接计算元素在当前层数组中的下标省了一次遍历写起来也更干净。要注意size必须在进入循环前记录因为队列在循环中会不断变化直接写q.size()会在循环过程中被改变导致边界错误。4.2 数据库题一条慢SQL的优化全流程还有一道数据库题给了一张订单表和一张商品表要求查询“每个商品最近一笔订单”的记录。很多人第一反应是直接写GROUP BY然后取MAX(order_time)但题目要求的是整行记录而不是聚合后的结果直接分组拿不到完整的订单信息。这道题的考点有两个一是子查询的用法二是如何避免“只出现在GROUP BY中的列才能被SELECT”这个限制。比较稳妥的解法是先查出一个子集即每个商品的最大订单时间然后用原表去关联这个子集拿到完整记录SELECT o.* FROM orders o JOIN ( SELECT product_id, MAX(order_time) AS max_time FROM orders GROUP BY product_id ) t ON o.product_id t.product_id AND o.order_time t.max_time这个解法的核心是利用自连接替代分组加非聚合列的查询避免很多数据库在ONLY_FULL_GROUP_BY模式下直接报错。注意如果同一商品在同一秒内有两笔订单上面的写法会查出多行需要再根据订单号去掉多余记录。实际业务里订单时间一般精确到毫秒重复概率低但笔试时答出这个特殊情况会加分不少。4.3 综合逻辑题跳出题目的陷阱逻辑题里面有一道很典型的“真假话”题大致是张三说“李四在说谎”李四说“王五在说谎”王五说“张三和李四都在说谎”问谁说真话。这类题看着绕其实一个表格就能搞定。假设张三说真话那么李四就在说谎王五说真话但王五说“张三和李四都在说谎”这和张三说真话矛盾所以张三不可能说真话。假设张三说真话这条路走不通那就假设张三在说谎推出李四说真话进而王五在说谎逻辑自洽。所以答案是李四说真话。解这种题的关键是不要凭直觉选把每个假设都列出来遇到矛盾就排除最终剩下的就是答案。笔试时用草稿纸画个表格两分钟就能解完。5. 备考时间规划与笔试现场策略5.1 三个月备考时间线怎么排如果你现在还处于“听说过校招笔试但还没系统刷题”的阶段我强烈建议你不要裸考。当年我认识不少同学技术还行但第一次做笔试就被时间打懵了题没做完心态崩了后面发挥直线下降。备考这件事三个月刚刚好。第一个月主攻基础C语言或你主攻语言的核心语法、数据结构的基础操作、计算机网络和操作系统的高频考点。这一个月不用刷太多题重点是看知识点建立完整的知识体系。看书的时候要动手敲代码尤其是二叉树遍历、排序算法、链表操作这些光看会了不算会手写不出来就是不会。第二个月进入刷题模式每天保证一到两套模拟题或真题按真实笔试的时间限制来模拟。刷题过程中把错题整理到文档里每道题的错因分三类知识点盲区、粗心大意、思路有问题。知识点盲区要回头翻书补齐思路问题要多看题解、多总结套路。这个阶段不要贪多吃透一套题比草草刷三套题更有用。第三个月进入冲刺模式重点做编程题把各类高频题型过一遍比如链表操作、二叉树、动态规划、字符串处理、二分法。同时复盘前两个月的错题再刷一遍确保闭着眼睛也能写出来。搞一套自己的答题模板比如二叉树遍历的模板、快排的模板、动态规划的模板考场上直接用模板能省很多思考时间。5.2 笔试现场的时间分配与做题顺序笔试现场最怕的不是题难而是时间分配失误。以这套卷子为例题型分布是选择题、简答题、编程题几种我的做题顺序建议是先做选择题和简答题里自己最有把握的板块再做编程题最后回头处理拿不准的题目。选择题部分一分钟内没思路就先标记跳过不要死磕。很多同学在选择题上花太久导致后面编程题时间不够这是最亏的。一般来说一份90分钟的题目选择题加简答题最好控制在40分钟内剩下50分钟全留给编程题和压轴题。编程题先看分值和难度先做自己有思路的把能拿的分拿稳再去啃硬骨头。编程题做完一定要检查边界条件比如输入为空、数组只有一个元素、数值特别大的情况。我见过太多人代码逻辑没问题唯独漏了空指针判断测试用例直接挂掉非常可惜。还有一个容易被忽视的点笔试一般允许使用本地IDE但有些环境不能联网。平时练习时一定要习惯不借助搜索引擎写代码否则考场上你会非常被动。6. 过来人踩坑记录五个高频翻车点与避坑方案翻车点典型表现避坑方案选择题过度纠结一道不会的题死磕5分钟先跳过做完所有题再回头边界条件漏判数组为空、字符串为空时程序崩溃写完后专门花2分钟检查边界算法题只写思路不写代码以为面试官只看思路笔试环境最终以运行结果为准时间分配失衡选择题耗时过多编程题没时间平时模拟时按比例分配时间忽略错题整理同一类题反复错错题本按知识点分类冲刺阶段反复看这五个坑我自己全踩过尤其是第二个印象最深。有一次模拟笔试我的二叉树层序遍历代码逻辑完全正确就是因为没判断根节点是否为空在测试用例上直接空指针异常当场扣了不少分。从那以后我每次写完代码都会加一个固定的检查步骤边界条件确认、变量初始化确认、循环边界确认。这套流程救了我很多次。另外不要小看那些看上去很基础的概念题比如TCP三次握手、进程与线程的区别、数据库中WHERE与HAVING的取舍。这类题往往是选择题里的“送分题”但也是很多人丢分的地方因为太基础了反而被轻视。基础题不丢分难题能拿一半分笔试基本就稳了。我个人在复盘历年真题时最大的感受是校招笔试没有那么多“奇技淫巧”考的就是你大学四年到底学得扎不扎实。而这份2017年的搜狐模拟笔试题二就是检验基本功是否扎实的一面镜子。如果你能把这套题里涉及的所有知识点都吃透再去做其他公司的笔试题你会发现自己的底气完全不一样。备考没有捷径把基础打牢比刷一百套题都有用。