
2018年搜狐秋招第二批技术类试卷我到现在还记得拿到手的那股感觉题型不花哨考点不偏门可每一道题都像在检查你“是不是真的写过代码”。那会儿我正值秋招季做了不下二十套各厂的笔试题对比下来搜狐这套卷子属于典型的“基础扎实型”选手筛选题——它不靠偏题怪题难倒你而是靠那些“你以为你会、但没完全会”的基础概念把真正有工程素养的候选人和临时抱佛脚的应届生区分开。如果你正准备互联网公司的技术岗笔试尤其是后端、算法、客户端方向这套试卷值得反复琢磨。它能帮你检验计算机基础四件套掌握得结不结实也能让你直观感受到搜狐这种老牌互联网公司在选拔技术人才时的出题偏好。我后来花了一周时间把每道题翻出来逐项复盘今天就把这套试卷的考察逻辑、核心知识点和实战心得整理出来希望对你有用。1. 试卷整体设计与考察思路拆解1.1 搜狐技术笔试出题的基本逻辑一份技术笔试的卷面设计往往能反映这家公司真实的工程文化和技术栈需求。搜狐2018秋招第二批技术类试卷的目标岗位以后端开发、算法工程和客户端开发为主而它当时的业务重心在资讯、视频、社交产品上这些产品有一个共同特点高并发读取、内容分发链路长、老系统多。这意味着什么意味着工程师入职后大概率要维护存量代码、排查线上性能问题、在复杂的网络环境下保障服务稳定性。这些工作落到笔试考察上就变成了对计算机基本功的深挖而不是对某个冷门框架的背诵。我把这套卷子的出题逻辑拆成三层来看。第一层是考察候选人基础知识的完整度。进程和线程的区别、TCP三次握手的状态变化、B树索引为什么快这些概念从大二听到大四但每次落笔写答案时都能暴露理解深度。搜狐的卷子尤其喜欢在这些“基础题”上设置容易混淆的选项比如把TIME_WAIT状态放在主动关闭方还是被动关闭方、哈希表用链地址法还是开放定址法解决冲突全是概念临近项。第二层是考察候选人的边界处理能力。卷子里手写代码的题目不算难但题目描述里经常藏着边界条件要求数组长度可能为0、链表可能有环、括号字符串可能为空。这其实是在模拟真实工程场景——线上代码不可能只处理教科书里的标准输入你写的每一行代码都要考虑异常分支。第三层是考察候选人的代码风格与自解释能力。我当时在纸质试卷上手写代码明显感觉到阅卷人会看你变量命名是否清晰、是否有注释、是否主动说明复杂度。这不是形式主义而是工程协作的基本素养。代码是写给人看的顺带让机器执行这个理念在搜狐的笔试中体现得淋漓尽致。1.2 考察范围与知识点分布明细综合当时参加笔试的回忆和后续跟同学讨论的结果第二批技术类试卷大致可以按下面这个分布来理解知识模块常见考察形式大致分值占比算法与数据结构选择题、手写编程题30%计算机网络选择题、简答题20%操作系统选择题、简答题20%数据库选择题、SQL手写题15%系统设计/场景综合简答题、设计题15%这个分值分布放在2018年看并不意外即便放到现在也很有参考价值。算法和数据结构占比最高这是所有互联网公司技术笔试的标配网络和操作系统加起来占了四成说明搜狐对候选人的服务端基础能力有明确预期数据库占比虽然不算高但SQL题往往是拉开差距的关键因为很多人算法题刷得溜SQL却写不顺畅。值得注意的是这份试卷几乎没有考察任何特定框架的使用细节比如不问你Spring Boot的某个注解怎么用、不问你Redis的某个命令语法。这传递了一个信号校招更看重候选人的可塑性框架可以入职后学但计算机基础必须在校招前打好底子。这一点我觉得对准备笔试的思路很有指导意义——与其背框架八股不如把基础科目复习扎实。2. 算法与数据结构真题解析2.1 字符串与数组题型别急着写循环算法题是这份试卷的重头戏但搜狐不走“上来就给你一道难题下马威”的路线。第二批试卷的编程题整体难度属于中等偏下可就因为题目看起来简单翻车率反而高。我印象最深的一道题是判断括号字符串是否有效题目描述很简单给定一个只包含()[]{}的字符串判断字符串是否有效有效规则是左括号必须用相同类型右括号闭合并且要按正确顺序闭合。这道题的标准解法是用栈遇到左括号入栈遇到右括号弹出栈顶元素并判断是否匹配最后检查栈是否为空。核心实现如下def is_valid(s: str) - bool: stack [] mapping {): (, ]: [, }: {} for ch in s: if ch in mapping: if not stack or stack[-1] ! mapping[ch]: return False stack.pop() else: stack.append(ch) return not stack看起来轻巧但当时考场上至少有三个高频翻车点。第一是只考虑括号数量对称而忽略类型匹配比如([)]这种字符串数量上左右相等实际是无效的第二是遍历完字符串后忘记检查栈是否为空只判断中间过程导致((()被错误判定为有效第三是没处理空字符串边界虽然空字符串按定义也算有效但很多人一上来就写if not s: return False反而把正确条件写反了。另一个有代表性的题目是“两数之和”。给定一个整数数组和一个目标值要求返回两个数字的索引。题目里还有个提示问能不能用优于O(n^2)的复杂度完成基本就是在引导你用哈希表。暴力双循环谁都会写但工程上必须考虑数据规模一道题能不能从O(n^2)优化到O(n)体现的是对时间复杂度的敏感度。用哈希表的思路很简单遍历数组时把每个元素的值和下标存入字典同时检查target - 当前值是否已经出现在字典中如果出现过就直接返回两个下标。我复盘时最大的体会是这道题搜狐考察的其实不是你会不会用哈希表而是你在编写代码时有没有主动说明复杂度的习惯。我在答案末尾写了一行“时间复杂度O(n)空间复杂度O(n)”这行字在阅卷时大概率是加分项因为它展示了工程师的思维习惯。2.2 链表与二叉树基本功试金石链表反转是搜狐这类公司手写算法题里出现频率最高的题目之一2018年第二批也不例外。题目要求反转一个单链表并返回新的头节点。迭代写法如下def reverse_list(head): prev None cur head while cur: nxt cur.next cur.next prev prev cur cur nxt return prev这段代码踩过坑的人都知道最核心的三行是nxt cur.next、cur.next prev、prev, cur cur, nxt的顺序不能乱。很多人在考场上会忘记保存nxt导致当前节点指针被修改后无法继续遍历还有人会把cur cur.next写成cur nxt之前就做了但cur.next已经指向前一个节点再这么写就直接死循环了。链表题考验的从来不是思路而是你对指针操作的肌肉记忆。二叉树层次遍历也是这套卷子的常客。题干一般会给一个二叉树要求按层输出节点值。这里需要注意一个细节题目可能要求按层输出成二维数组而不是简单打印节点的访问顺序。很多只写过基础BFS的同学会在这一步翻车因为基础BFS用一个队列就能完成但按层输出需要记录当前层的节点数量。def level_order(root): if not root: return [] result [] queue [root] while queue: level_size len(queue) level_nodes [] for _ in range(level_size): node queue.pop(0) level_nodes.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level_nodes) return result关键就在level_size len(queue)这一行进循环先固定当前层的节点数然后只处理这么多节点这样才不会把下一层的节点混到当前层来。这个处理方式在现实中也很有用比如按用户层级做推荐分发、按目录层级做权限统计都会用到类似的“层内定长”技巧。数据结构的选择题部分同样值得盯防我整理了几个高频易错点栈和队列的进出顺序、哈希冲突的常见解决方式、二叉搜索树中序遍历结果是升序序列。这几个点几乎年年考但每年都有人因为概念混淆丢分。我的建议是复习时把这些结论的推导过程过一遍而不是只背结论这样遇到变体题才不会慌。3. 计算机网络与操作系统核心考点3.1 TCP三次握手与HTTP协议必考中的必考搜狐的业务以内容分发为主后端接口被用户高频调用任何技术岗候选人都必须对网络协议有足够深的理解。试卷里计算机网络部分的题目集中在几个固定板块TCP三次握手和四次挥手、HTTP常用状态码、HTTP无状态特性和Cookie/Session的配合、TCP可靠性机制。其中“为什么TCP建立连接需要三次握手而不能是两次”是出现频率极高的一道题。我在整理答案时习惯用“确认双方收发能力”来回答第一次握手客户端发送SYN服务端确认了客户端的发送能力第二次握手服务端发送SYNACK客户端确认了服务端的发送和接收能力第三次握手客户端发送ACK服务端确认了客户端的接收能力。如果是两次握手服务端无法确认客户端的接收能力在不可靠网络中一个已经失效的旧连接请求可能突然到达服务端导致服务端白白建立连接、浪费资源。这个解释比单纯背诵“为了确认序列号”要完整得多阅卷人看到这种答案也会觉得你是真的理解了。四次挥手里的TIME_WAIT状态也是选择题常客。TIME_WAIT出现在主动关闭连接的一方作用是确保最后一个ACK能到达对方、同时让本连接中滞留的报文段在网络中过期失效。很多同学会混淆主动关闭方和被动关闭方的状态变化我的记忆技巧是把四次挥手想象成“两个人说再见”A说我要走了B说好的我知道了B又说那我也走了A说好最后A在原地多等一会儿TIME_WAIT才真正离开。讲给学弟听的时候这个类比基本上一次就能记住。HTTP状态码的考察相对简单但选项往往设置得很细。200表示成功301是永久重定向302是临时重定向403是服务器拒绝执行404是请求资源不存在500是服务器内部错误502是网关错误。我在这类题上丢过分原因是把301和302搞混了。后来我记了一个方法看到“永久”就想到“搬家了”搬家后旧地址就不该再用了所以是301临时转场才是302。这样想就再也没错过。3.2 进程线程模型与内存管理细节操作系统模块在搜狐试卷里占比不低而且题目风格偏概念辨析喜欢在相近的概念之间做文章。我当时总结的高频考点有四个进程和线程的区别、死锁产生的四个必要条件、虚拟内存与分页机制、进程调度算法。进程和线程的经典考点回答框架其实很固定进程是资源分配的最小单位线程是CPU调度的最小单位每个进程拥有独立的地址空间同一个进程的多个线程共享地址空间进程切换开销大于线程切换进程间通信用管道、消息队列、共享内存、信号量线程间通信用共享变量、互斥锁、条件变量。这些框架分列清楚选择题基本不会失手。真正容易翻车的是“下面哪个操作可能导致用户态到内核态的切换”这类题。很多人只选了系统调用忽略了缺页异常和外部中断这两个选项。事实上用户态到内核态的切换通常有三类触发原因系统调用、异常如缺页、外围设备中断。这道题让我后来复习操作系统时格外注意概念的完整性不能只背典型例子要把所有触发路径都过一遍。死锁的四个必要条件——互斥、持有并等待、不可剥夺、循环等待——也是必考内容。选择题通常会给四个场景问哪个不会导致死锁。这时候用排除法最稳只要四个条件里缺一个死锁就不会发生。比如“资源可以被抢占”这种描述实际上破坏的是不可剥夺条件所以不会导致死锁。另外还要知道常见的死锁避免策略比如破坏循环等待条件的方法是给资源编号、按序分配银行家算法则是预防死锁的经典方法。内存管理部分重点理解虚拟内存的意义它让每个进程认为自己拥有连续的地址空间同时把物理内存和进程地址空间解耦通过分页机制按需加载。缺页异常发生在访问的页面不在物理内存时此时操作系统需要从磁盘调入页面。这个概念不理解透彻后面遇到“为什么程序能跑在比物理内存更大的地址空间里”这类题就容易发懵。我的建议是把“一个程序从启动到结束内存里发生了什么”完整想一遍虚拟内存、页表、缺页中断这些知识点就都串起来了。4. 数据库与综合基础题剖析4.1 SQL手写题JOIN类型辨析与分组统计数据库部分搜狐笔试一般不会只考背诵型选择填空而是给你一张业务表要求写出统计SQL。我记得当年的题干大概是内容表和用户操作表要求统计某段时间内每个分类下被操作的次数按次数降序排列。这类SQL题是数据库模块的拿分题但同时是很多人的失分题。统计每个分类下的内容数量按数量排序输出核心写法如下SELECT category, COUNT(*) AS cnt FROM contents WHERE create_time 2018-08-01 GROUP BY category ORDER BY cnt DESC;这道题有三层考察点。第一层是GROUP BY的语法规范SELECT子句里出现的非聚合字段必须是GROUP BY的分组字段很多人写SELECT category, content_name, COUNT(*)却只按category分组直接报错。第二层是WHERE和HAVING的使用时机过滤分组前的行用WHERE过滤分组后的条件用HAVING比如“只统计数量大于10的分类”就得写HAVING COUNT(*) 10。第三层是ORDER BY能不能用别名在MySQL中ORDER BY cnt是允许的但为了可移植性有些团队规范会要求写完整表达式。JOIN类型辨析几乎是必考最常见的是INNER JOIN和LEFT JOIN的区别。考试里给过一个经典场景给定用户表和订单表找出没有下过单的用户。很多新手第一反应是NOT IN但这里有个坑——如果子查询结果中包含NULLNOT IN的返回结果会变成空集导致整个查询结果错误。更稳妥的写法是使用LEFT JOIN加IS NULL判断SELECT u.user_id, u.user_name FROM users u LEFT JOIN orders o ON u.user_id o.user_id WHERE o.order_id IS NULL;这个写法利用的是LEFT JOIN的特性左表记录全部保留右表没有匹配记录时补NULL。再加上WHERE o.order_id IS NULL就精确筛选出那些从未下过单的用户。我在复盘时把INNER JOIN和LEFT JOIN的区别整理成一句话INNER JOIN是“两边都有才算有”LEFT JOIN是“左边的一定要有右边的有才算有”。这句话帮很多同学秒懂了JOIN语义。4.2 索引、事务与场景设计题数据库选择题部分高频考点包括索引底层实现为什么选B树、事务ACID特性、隔离级别、InnoDB的默认隔离级别。其中“为什么选B树”这个题可以从三个角度回答B树高度低通常三四层就能支撑千万级别数据叶子节点之间通过指针构成有序链表非常适合范围查询所有数据都存在叶子节点上查询性能稳定。对比哈希索引虽然等值查询快但不支持范围查询二叉树在数据量大时高度过高查询效率下降。把这个逻辑说清楚比单纯背结论有说服力得多。事务的隔离级别从低到高是读未提交、读已提交、可重复读、串行化。隔离级别越高一致性越强但并发性能越低。InnoDB默认隔离级别是可重复读但它通过间隙锁机制解决了幻读问题所以实际效果接近串行化。这个知识点是面试加分项如果考场上能写出来阅卷人会觉得你的知识体系是完整的。场景设计题是搜狐试卷的特色题。这类题看起来像“聊天题”但需要写出具体的方案。我记得当时有一道短链服务设计题要求给出核心表结构和主要流程。我当时的答题框架是先设计表结构包含自增主键id、短码short_code、原始URL、创建时间和过期时间短码生成方式用62进制编码把数字id转换为由大小写字母和数字组成的短码这样能极大缩短URL长度写入时先检查short_code是否冲突冲突就重新生成读取时先查缓存缓存未命中再查数据库并回填缓存过期清理用惰性删除和定期任务配合。答题的关键在于“具体”。我当时写了具体的字段名和接口流程哪怕方案简陋也比空泛地写“用数据库存一下”要好得多。阅卷人最怕看到大而空的描述你写了表结构、写了唯一索引、写了缓存更新策略他就知道你是真的思考过这类问题。面试中遇到类似的设计题这也是一个可靠的答题思路。5. 常见问题与实操经验5.1 笔试现场的时间分配与答题顺序搜狐2018秋招第二批的卷子整体题量偏大选择题的选项设计又很有迷惑性稍不留神就会在前面花掉太多时间导致后面的手写代码题和SQL题草草了事。我自己就踩过这个坑在一道链表编程题上反复涂改后面最有把握的SQL题反而只写了一半交卷后懊恼不已。复盘之后我总结了一套适用于这类笔试的答题顺序分享给你参考。拿到试卷的前两分钟不要急着动笔先快速通览全卷在题目旁边做标记一眼能写出答案的题直接标“先做”需要思考的题标“后做”完全没有思路的标“最后做”。然后按照“编程题优先、SQL题次之、选择题最后”的顺序推进。手写代码题分值高有步骤分先把你能拿的分拿到SQL题通常是业务场景题思路正确就有分选择题如果卡住了先标记跳过去不要在一道题上耗超过三分钟。时间分配上我的建议是选择题控制在25分钟左右简答题控制在20分钟编程题和SQL题留40分钟最后剩5到10分钟做整体检查。检查时重点看手写代码的边界条件、变量名前后是否一致、有没有把大于号和小于号写反。这些低级错误在紧张状态下很容易出现。5.2 针对搜狐题型的准备建议如果你把搜狐这类业务型互联网公司定为目标准备阶段可以参考我下面的做法。这里不讲大而全的“操作系统全书复习法”只讲高效的应试策略。刷题方向上重点放在数组、字符串、链表、二叉树刷LeetCode前150题足够应对搜狐笔试的算法难度跟LeetCode高频题重合度很高。计算机网络部分TCP/UDP、HTTP、DNS这三块反复吃透配合抓包工具看一遍真实请求状态码和报文格式会记得更牢。操作系统部分把进程线程、内存管理、I/O多路复用梳理成自己的知识树不要零散地背概念。数据库部分至少能默写出来用户表、订单表、商品表之间常用的JOIN查询和分组统计。同时每周做一次90分钟限时模拟用历年真题或者LeetCode组合卷都行关键是模拟考场节奏。另外要提一个细节这类笔试有些是用在线编辑器有些则发纸质试卷。2018年搜狐第二批就是纸质试卷手写代码时必须注意卷面整洁、缩进清晰、变量名易懂不要把a、b、c这种命名带到试卷上。阅卷老师是按人眼阅读的你的代码写得越像可以提交到代码仓库的样子他给你高分的意愿就越强。5.3 关于“笔试过了却面试挂掉”的复盘我身边不止一个同学倒在笔试通过后的面试环节回头看问题往往不在技术深度而在笔试答案里暴露的思考习惯。比如有一道设计题要求设计一个缓存淘汰策略他在试卷上只写了一个“LRU”名词没有展开说数据结构也没有分析get和set操作的复杂度。阅卷人想看到的答案是用哈希表加双向链表实现LRUget和set都是O(1)删除节点时双向链表能直接拿到前驱节点所以比单向链表更合适。这些细节才是设计题的得分点。我也用这个标准审视自己平时做算法题时有没有养成“写完代码口头给自己讲一遍”的习惯后来我每做完一道题就模拟面试官提问问自己为什么这么写、还有没有更优方案、边界情况怎么处理。几次练习下来笔试时的输出明显更有条理语言组织也更流畅。5.4 常见问题速查表我把当年笔试结束后大家讨论最多的问题整理成一张速查表方便你复习时快速定位问题易错点正确思路括号字符串匹配忘记类型匹配或栈空用栈匹配并检查栈空两数之和暴力O(n^2)哈希表O(n)链表反转丢失后继指针先保存nxt再改指向TCP两次挥手够吗混淆两次握手目的三次握手确认双方收发能力TIME_WAIT位置常误选被动关闭方主动关闭方确保ACK到达死锁条件只记三个条件互斥、持有并等待、不可剥夺、循环等待NOT IN含NULL子查询结果含NULL时返回空用LEFT JOIN IS NULL分组统计排序GROUP BY字段混乱SELECT字段必须包含分组字段或聚合函数LRU设计只写名词不展开哈希表双向链表get/set均为O(1)这张表里的问题几乎覆盖了搜狐2018秋招第二批技术类试卷的核心考察点。它能帮你在考前快速做一遍自检哪些概念能脱口而出哪些还需要再翻书一目了然。我在实际备考中最大的感受是校招笔试拼的从来不是天赋而是信息差和熟练度。把每套真题的知识点拆到位、把每类问题的答题套路练熟、把考场节奏控制好通过率自然就上去了。这份搜狐试卷的复盘写到这里希望能帮你少走一些我当年走过的弯路。