2016百度研发工程师笔试题复盘:算法与计算机基础全攻略 📅 发布时间:2026/8/30 12:15:50 👁 浏览次数: 1. 这套题到底在考什么研发岗的筛选逻辑1.1 研发笔试题的定位不是刁难是筛选思维方式很多准备校招的同学一听到百度笔试就紧张觉得题目应该又偏又难。实际上从我当年刷题到后来帮着部门做笔试题复盘我的感受是大厂的研发工程师笔试题考察的核心不是“你背了多少书”而是“你在有限时间内解决陌生问题的能力”。它的本质是一套筛选机制的入口——通过几个小时的题目把候选人分成两类一类是真正具备工程思维、基本功扎实的人另一类是靠着临时抱佛脚、记忆碎片化知识点的人。2016年的这套研发工程师笔试题六在当年的题库里算是比较有代表性的一套。它延续了百度一贯的出题风格重视算法与数据结构穿插操作系统、网络、数据库等计算机基础再混合几道逻辑推理和编程题。整套试卷的题量不算特别大但覆盖的面非常广时间压力也不小。很多人在考场上会觉得“每道题都见过但没有一道能完全拿得准”——这正是出题人想要的效果。笔试不是为了让你得满分而是让你在压力下暴露真实的思维习惯。我在复盘这套题的时候最大的感受是它考察的并不只是知识点本身而是你对知识点的理解深度。比如同样一道二分法变体题有的人能立刻写出正确代码并处理边界条件有的人却在循环条件上卡了二十分钟。差距不在“知不知道二分法”而在“是否真的理解二分法为什么这样写”。所以这篇文章我不是来给你报答案的而是想帮你建立一个更完整的视角这套题背后考的是什么每类题目该怎么思考以及在你准备面试时应该把精力放在哪里才能真正提升。无论你是正在准备校招、社招跳槽还是纯粹想检验一下自己的计算机基础能力这套题的复盘都值得你花一篇文章的时间读下去。1.2 题型分布与分值逻辑十分钟定胜负的硬功夫我仔细拆过这套题的结构它大致包含几类题目选择题涵盖数据结构、操作系统、网络、数据库、概率论等、编程题通常是算法实现、以及简答或逻辑推理题。选择题数量最多单题分值不高但正确率决定了你能不能进入后面的编程题环节编程题通常占大头一般是一到两道分值占比往往在30%到40%之间。这里有一个很多考生容易忽略的细节选择题并不仅仅是“送分题”。百度的选择题出得非常“狡猾”它经常会把一个正确选项藏在三个近似正确的选项中间。如果你对某个概念的理解只停留在“好像是这样”的层面一道选择题就会暴露无遗。比如题目可能问你“哪些操作会导致进程从用户态切换到内核态”选项里既有“系统调用”“缺页异常”“修改进程私有变量”这种容易混淆的选项如果你对用户态和内核态切换的触发条件理解不深很容易选错。另一个值得注意的点是时间分配。以我自己的经验这套题的合理节奏是选择题每道控制在两分钟以内遇到卡壳的先标记跳过编程题留足四十分钟以上。为什么因为编程题只要思路对了、代码能跑通就是一道大题的分数而一道选择题只有一两分纠结太久反而得不偿失。很多人在考场上出的最大问题不是不会做而是把时间全耗在了几道有争议的选择题上最后编程题只剩十几分钟胡乱写了个框架白白丢掉了最大分值。所以在拆这套题之前我建议你先建立这样一个认知这是一场时间管理能力与基础知识深度的综合测试不是单纯的知识记忆比赛。下面我按题型和考点逐一拆解看看每一类题目背后到底在考察什么能力。2. 高频考点逐项拆解笔试背后的计算机基本功2.1 数据结构与算法笔试的绝对主角不管哪一年的百度笔试数据结构与算法永远是占比最高、最能拉开差距的部分。这套2016年的题目里算法的考察集中在几个经典模型上链表操作、二叉树遍历、排序与查找、动态规划。表面上看起来都是“老面孔”但出题人会通过改变条件或者增加限制把经典问题变成新的挑战。先说链表。有一道典型的题目是“判断单链表是否存在环并找出环的入口节点”。这题很多人在面试前都背过答案用快慢指针快指针每次走两步慢指针每次走一步如果有环则两者必定相遇然后调整其中一个指针重新遍历再次相遇的位置就是环入口。但考试不会只让你说思路它会在选项或者后续问题里追问多个细节比如“如果链表长度为n快慢指针最坏情况下要移动多少步”“是否存在无法判断的情况”等。如果你只背结论而没推导过过程这些追问就是送命题。再比如二叉树。这套题里有一道层次遍历的变体不是让你按层输出而是让你按“之字形”顺序输出。这题的常规解法是用两个栈或者双向队列在奇数层从左到右入队偶数层从右到左入队。如果你只会用单队列做标准层次遍历遇到这种变体就会卡壳。我在实际辅导同学的时候经常强调不要背题要背“解法背后的数据结构性质”。队列为什么能实现层次遍历因为先进先出保证了同一层节点按顺序被访问。栈为什么能实现逆序因为后进先出天然将顺序反转。理解了这两点之字形遍历就是一个很自然的扩展。算法题的另一个大头是动态规划。这套题里有一道“最大连续子数组和”的变体给定一个数组允许你最多交换两个元素的位置求交换后最大连续子数组和的最大值。经典的Kadane算法大家都会但加了一个“交换”操作后问题的状态空间立刻变大。这种题考察的已经不是“会不会动态规划”而是“能不能重新抽象问题、找到合适的状态定义”。我对这类题的建议是先写暴力解把问题完全理解清楚之后再去想怎么优化。很多时候笔试考场上你就算写不出最优解写一个暴力的正确解也能拿到大部分分数因为评分是按测试用例通过的百分比来算的。还有排序算法。这套题里应该有一道关于排序稳定性的选择题问哪些排序算法是稳定的哪些是不稳定的。这个知识点本身不难但有几个坑比如“堆排序是否稳定”“快速排序在什么情况下最坏”“归并排序的空间复杂度”。我遇到过很多同学能说出“快排不稳定”但问“为什么不稳定”就说不清了。其实核心在于稳定性指的是相等元素的相对顺序在排序后保持不变。快排的分区操作是跳跃式交换不能保证相等元素的相对次序所以不稳定归并排序在合并时只要判断条件写成“左半部分的元素小于等于右半部分才取左边”就能保持稳定。这种细节笔试直接考面世也经常问值得彻底搞清楚。2.2 操作系统与网络决定能否进入面试的隐形门槛算法题决定你能拿多少分而操作系统和网络的题目很多时候决定的是你能否跨过及格线。从2016百度这套题来看操作系统和网络的考察点集中在进程与线程、死锁、内存管理、TCP协议、HTTP协议、DNS解析等。这些题目不是单纯记忆而是需要你理解“为什么这么做”。举一个典型例子死锁产生的四个必要条件——互斥、持有并等待、不可剥夺、循环等待。选择题不会直接问你这四个条件是什么而是给你一个具体场景问你这个场景破坏了哪个条件从而可以避免死锁。比如“一个进程在请求资源失败时主动释放已持有的资源”这破坏的是“不可剥夺”条件。如果你只是背了四个名词没有理解每个条件的真实含义这种题目就会变得非常模糊。内存管理也是一个高频考点。这套题里可能涉及分页与分段、虚拟内存、页面置换算法。我记得有一道关于LRU算法的题给一个访问序列和一个物理块数问缺页次数是多少。这题的核心是模拟但很多人会在“某页被访问时是否算缺页”这个细节上出错。只要你理解LRU的思想是“最近最久未使用的页面被换出”并且每次访问时先查找页面是否在内存中不在才产生缺页这个模拟过程就不会错。我可以明确说这种题目是送分题只要仔仔细细画一张表基本上不可能出错。网络部分的考题比操作系统更“实用”。TCP三次握手几乎是必考内容但这套题的问法往往不直接问你“三次握手是什么”而是问“为什么两次握手不可以”“SYN泛洪是什么”“第三次握手丢包了会发生什么”。要答好这些问题你需要真正理解三次握手是为了保证双方都有发送和接收能力以及序列号同步。还有一道与时间等待有关的Time_Wait问题为什么主动关闭方要进入TIME_WAIT状态并等待2MSL因为要确保最后一个ACK能够到达对方以及让网络中延迟的报文段自然消失避免影响新的连接。这种题考的是理解不是背诵。HTTP相关题目也比较典型比如“GET和POST的区别”“HTTP状态码的含义”“Cookie和Session的关系”。这些题目看起来简单但出题人会设置很多陷阱。比如“GET请求能否携带请求体”——从规范上讲可以但不是所有服务器都支持所以最稳妥的答案是“不建议携带规范也没有规定必须支持”。这种“看似确定实则模糊”的题目最能区分出你是真懂还是只是记住了教科书。我给准备笔试的同学一个建议把网络和操作系统的知识按“机制—原因—场景”三层去整理。机制是这个东西怎么工作原因是设计者为什么这么设计场景是它真实应用在什么地方。当你把每个知识点都这样过一遍再去做各类选择题你会发现出题人的所有干扰项都骗不了你。2.3 数据库与逻辑推理容易被忽视的送分与送命题很多准备笔试的同学把大量时间花在算法上对数据库和逻辑推理题不够重视。实际上从这套题的设计来看数据库题和逻辑题往往是整场考试的“平衡因子”——对于基础扎实的人它们是送分题对于基础薄弱的人它们是送命题。数据库部分的核心考点是索引、事务隔离级别、B树、SQL语法与优化。有一道很典型的题给一条SQL查询语句问这条查询是否能用上某个索引。这里面的坑在于很多人以为“WHERE条件里有索引列”就能走索引但实际上函数运算、隐式类型转换、前导模糊查询都可能导致索引失效。比如WHERE name LIKE %张这种后模糊匹配是没法走普通B树索引的。这道题背后的原理是B树索引的查找依赖前缀匹配。理解了这一点很多类似的问题都能迎刃而解。事务隔离级别也是高频考点尤其是“脏读”“不可重复读”“幻读”三者的区别以及每种隔离级别分别会避免哪些问题。我建议你把四种隔离级别列成一个表格对着记忆读未提交可能脏读、不可重复读、幻读读已提交避免脏读可能不可重复读和幻读可重复读避免脏读和不可重复读可能幻读可串行化全部避免。这套题里应该有一道题专门考察这个只要你把表格记住再理解每个“读”异常的含义就不会丢分。逻辑推理题则更偏向于思维能力测试。常见的形式有找规律、概率计算、条件推理。比如一道典型的概率题“A和B轮流抛硬币先抛出正面的人获胜A先抛问A获胜的概率是多少”这道题可以用等比级数求和轻松解出来A在第一轮赢的概率是1/2第二轮赢的概率是1/8第三轮是1/32所以总概率是(1/2) / (1 - 1/4) 2/3。这类题目其实并不难难的是考场上能不能快速想到用级数求和而不是盲目列举。逻辑题里还有一种“真假话”问题几个人分别说了一句话只有一个人说真话问谁在说谎。这种题的标准解法是假设法加矛盾检测。我在考场上有一套固定的流程先假设某个人说的是真话推导其他人口供的真实性出现矛盾就换一个假设。这个方法虽然笨但一定正确而且不太容易出错。3. 典型真题实战推演从读题到写码的完整过程3.1 一步步拆解链表题的边界条件与证明思路还记得以前我刷这套题时遇到一道非常典型的链表题题目大意是“给定两个单链表判断它们是否相交如果相交则返回第一个相交节点”。这个题在2016年前后的大厂笔试出现频率很高而且解法有很多种出题人喜欢把它出成编程题让你完整实现。拿到题目第一步不是急着写代码而是要明确“相交”的定义。单链表相交指的是两个链表从某个节点开始后面的节点全部相同而不是仅仅某个节点的值相同。因为链表的节点是通过指针连接的两个链表如果相交它们的最后一个节点一定相同。这个性质可以很快判断两个链表是否相交直接遍历到两个链表的尾节点比较尾节点的内存地址是否相等。但题目要求的是“第一个相交节点”这就需要一个更精细的方法。最直观的思路是分别计算两个链表的长度假设长度差为d让长链表的指针先走d步然后两个指针同时出发第一次相遇的节点就是相交节点。为什么这样是对的因为两个链表从相交点开始到末尾是完全重合的所以把长链表多出的那段先走掉剩下的部分长度就一样了同步遍历时必然同时到达相交点。这个思路的时间复杂度是O(mn)空间复杂度是O(1)在笔试中已经是很优秀的解法。代码实现时要注意几个边界条件链表为空时直接返回NULL两个链表长度相等时不需要先走两个链表不相交时同步遍历会同时走到NULL。这里我想多说一句为什么笔试喜欢考这道题因为它考察的是你能否把一个看似复杂的问题转化为“先消除长度差”的简单问题。这种从特殊到一般、从复杂到简单的抽象能力恰恰是研发工程师在日常工作中最需要的。3.2 动态规划题的通用建模套路状态定义是核心动态规划题在笔试里是“分水岭”级别的存在。基础好的同学觉得它套路清晰基础差的同学觉得它变幻莫测。2016年这套题里的动态规划题其实并没有超出“经典DP模型”的范畴但它用了不少包装。以一道“最长公共子序列LCS”的变体为例。题目可能不会直接叫“最长公共子序列”而是包装成一个“字符串编辑”场景给定两个字符串问最少经过多少次插入、删除、替换操作可以让它们相等。这个问题本质上是编辑距离问题而编辑距离与LCS有非常紧密的联系。如果把问题转化为“先求LCS再进行操作计算”整个过程就会清晰很多。做这类DP题目我建议你遵循一套固定流程定义状态。这个是最关键的一步也是最需要练习的一步。编辑距离的状态定义是dp[i][j]表示字符串A的前i个字符转换为字符串B的前j个字符所需的最小操作次数。写状态转移方程。对于dp[i][j]如果A[i-1] B[j-1]那么dp[i][j] dp[i-1][j-1]否则dp[i][j] min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) 1。初始化边界。dp[i][0] idp[0][j] j表示从空串转换到另一个串需要全量插入或删除。优化与实现。如果用二维数组空间复杂度是O(mn)笔试能过如果想让代码更漂亮可以用滚动数组降到O(min(m,n))。我见过太多同学在状态定义这个环节卡住然后越写越乱。一个有效的练习方法是每做一道DP题先不写代码用自然语言把状态定义、转移方程、初始化和边界条件写清楚再动笔写代码。这样不仅思路清晰而且笔试现场也更容易检查出逻辑漏洞。3.3 操作系统题的分析路径画图永远比硬背简单操作系统题有一个特点只要你把过程的“图景”在脑子里建立起来很多选择题的答案就会变得非常直观。就拿那道经典的“虚拟内存页面置换”题目来说我当时在草稿纸上画了一张表格把访问序列、内存块内容、是否缺页逐行列出来答案一目了然。来回顾一下这个分析过程。假设页面访问序列是[1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5]物理块数是3用LRU算法问缺页次数。做法很机械第1次访问1内存为空缺页内存变为 [1]第2次访问2缺页内存变为 [1, 2]第3次访问3缺页内存变为 [1, 2, 3]第4次访问4内存满页面1是最久未使用的换出缺页内存变为 [2, 3, 4]依此类推直到最后。这个过程看起来简单但我在给同学讲题时发现一个特别容易搞混的点“最近最久未使用”不是“最早被装入的”。如果先访问了1之后又访问了2、3、4那么在1被换出之前2和3都已经被访问过它们的“最近使用时间”比1新。很多同学把这个搞反就会把应换出的页面选错最终缺页次数完全不同。所以解这类题的关键是画一张“时间线”图把每个页面最后一次被访问的时间标注出来。选“最久未使用”就是选“最近访问时间最老”的那个页面。这个方法虽然土但在笔试有限时间内非常有效。再讲一个与文件系统相关的考题思路给一个磁盘块大小、索引节点地址项数量问一个文件最大能有多大。这类题考的是对多级索引结构的理解。计算方法是分别计算直接块、一级间接块、二级间接块能指向的数据块数再乘以块大小求和。做题时最需要注意的是单位换算以及理解“块号占多少字节”这个参数如何影响每个间接块能容纳的指针数量。我在实际计算时习惯先在草稿纸上把“直接块多少块、一级间接多少块、二级间接多少块”列出来再代入公式避免遗漏。4. 那些年我们一起踩过的坑常见错误与排查经验4.1 审题失误的经典案例自以为是是最坑的我接触过不少笔试备考生也经常在他们考后复盘时发现丢分最惨的不是不会做的题而是“明明会做做错了”的题。我把这些错误分成几类每一类都能在2016年的试卷里找到对应场景。第一类是“没注意题目先决条件”。举例来说如果一道编程题要求“数组中的元素为整数且允许重复”你的解法却假设了元素不重复那后续的边界条件处理就会出问题。笔试题目中常常会出现“非负整数”“有序数组”“无重复元素”这些关键描述它们不仅仅是装饰而是直接影响算法选择的条件。很多人一看到“数组”两个字就把LeetCode上某道题的解法往上套完全不看题目问的差异这是最可惜的丢分方式。第二类是“忽略了数据范围”。很多大题会给出“n 10^5”这样的范围提示。如果你的解法是O(n^2)的复杂度在10万级别上就直接超时了即使你的代码逻辑正确也只能拿部分分数。我在做题时有一个习惯看完题目先看数据范围确定目标复杂度。如果n是10^5量级那基本意味着需要O(nlogn)或O(n)的解法这时候就可以主动排除一些笨重的方案。第三类是“产出格式不对”。算法题不是只要逻辑对就行题目的输入输出格式、换行、空格都必须完全一致。很多人栽在这个上面甚至自认为通过率100%的代码实际运行却是0%。我建议大家在笔试前熟悉牛客网或赛码网这类平台的输入解析方式练习时就用标准输入输出不要用调试器里的人工测试数据。4.2 编码细节空指针、溢出与死循环如果说审题是战略层面的失误那编码细节就是战术层面的翻车现场。这套题涉及的编程题不算特别复杂但考察的编码细节非常扎实。第一个高频坑是空指针。不管是链表题、树题还是数组题直接访问空指针的next、val是很多人的噩梦。例如遍历链表时循环条件是while (head)但你在循环体内不经判断就使用了head-next-val一旦这个链表只有一个节点代码就会崩溃。考试时这种错误很致命因为它不是逻辑错而是一个简单的防御性判断没有加上。我的习惯是凡是访问指针成员之前先问自己“这个指针在当前循环里是否可能为NULL”。如果可能就加一个条件判断。第二个高频坑是整数溢出。动态规划题尤其常见。比如求“最大子数组乘积”时你定义dp[i]为以i结尾的最大乘积子数组但你没有意识到负数乘以负数会变成正数导致你也需要维护一个最小乘积状态。这个坑在审查阶段非常隐蔽因为小规模测试数据根本测不出来。通用的做法是在状态转移过程中把当前最大值和最小值一起维护最后再取最大值。第三个高频坑是死循环尤其是在二分法变体、快慢指针这类题目中。我见过很多人在写二分查找时mid (left right) / 2在 left 和 right 相邻时可能出现left mid导致区间不再缩小最终死循环。这里有一个经验法则更新指针时要么left mid 1要么right mid - 1保证每一轮遍历区间都在缩小如果你写的更新是left mid或right mid一定要确认终止条件是否正确。用left right和left right配合的边界条件要分清否则非常容易出现死循环。4.3 时间分配的具体策略考场上的实战经验时间分配是个容易被低估的问题。以我的经验一套包含选择题和编程题的百度的试卷时间大概是一百二十分钟到一百五十分钟。很多人的失败不是智力问题而是节奏问题。我的个人建议是把时间分成三块第一块10到15分钟快速扫描所有题目标记出“送分题”“中等题”“难题”。不要在这个阶段做题只做标记。第二块70到80分钟按顺序做选择题遇到一道题思考超过三分之二分钟就立刻跳过去把有疑问的题目标记出来等做完一轮后再回头推敲。第三块剩余时间全部投入编程题。先写一个“能跑但可能不是最优”的正确解再逐步优化。这里有一个关键心态不要追求“完美答案”。选择题哪怕你完全不会也可以利用排除法、极限代入法去猜一个合理选项编程题哪怕只过了一个测试用例也比空着强。笔试是计分制不是按“胜负”定生死每一分都可能影响你能否进入面试。另外我强烈建议在平时练习时就养成时间管理的习惯。不要一道题做一两个小时那样到了实际考场一定会习惯性卡壳。给自己设定一个五分钟、十分钟、二十分钟的“思考上限”超过时限直接看题解并记录卡点这样才能在有限时间内覆盖更多题型。5. 从笔试到工程能力这些题目在工作中的影子5.1 算法题并不是“八股文”它对应的是真实系统的设计取舍很多人对笔试算法题有抵触情绪觉得“工作中根本不会手写快排、不会自己实现红黑树”。这句话只说对了一半。确实工作中大部分时候用现成库就够了但算法题训练的能力在工作里无处不在。就拿这套题里出现的“最大连续子数组和”来说它在实际工作中对应的是“如何从数据流中实时统计某个指标的最大波动区间”。再比如“判断链表是否有环”这类题在分布式系统里对应的是“如何检测引用关系中的循环依赖”。你也许不会真的手写一个链表环检测算法但你会依赖类似的思想去理解垃圾回收器、依赖解析器的工作原理。我在带团队做代码评审时经常发现一个问题有些同事能把业务代码写得非常流畅但一旦遇到性能瓶颈、数据量突增就不知道如何分析复杂度、如何选择合适的数据结构。这是典型的基本功缺失。笔试算法题恰恰是检验这种基本功最直接的方式。它不是八股文而是工程能力的缩影。5.2 这套题目训练出的能力如何迁移到日常工作里操作系统和网络题目同样不是“背了就忘”的知识它们直接决定了你排查线上问题的能力。我举一个真实的例子有一次我们的服务出现大量请求超时很多人第一反应是加机器扩容。但如果我们对TCP握手队列、全连接队列、TIME_WAIT状态这些概念有深刻理解就会先去看系统的连接状态发现TIME_WAIT堆积严重根本原因是一个短连接服务没有开启连接复用。这个排查过程用到的基础知识跟这套笔试题里“为什么需要2MSL”“TCP连接断开过程”几乎一模一样。笔试时的理解深度在关键时刻会转化成解决问题的效率。数据库的索引优化和事务隔离级别知识在业务开发里更是高频使用的硬技能。你写一条SQL能不能在刚写出来时就意识到它还有更好的写法、能不能预测它在千万级数据量下是否性能可控都依赖于对B树与索引原理的深刻理解。这些不是靠一两篇博客就能速成的而是需要你从笔试准备阶段就开始积累正确的思维模型。所以我一直认为准备笔试最好的心态不是“刷题背答案”而是“借题目检验自己的知识体系”。你把每一道错题都当成一次构建知识网络的机会当你把这些知识真正融会贯通之后你不仅通过了笔试你也在真正意义上接近了一个合格研发工程师的标准。最后再分享一个我个人的小习惯每次做完一套题不管是在牛客网上还是在纸质卷子上我都会把错题整理到一个文档里分门别类标注“考点”、“错误原因”和“正确思路”一周后重新做一遍。这个过程看起来费时间但效果远好于做十套新题。因为在笔试题这个领域里吃透一道经典题往往比浮光掠影地刷十道变形题更有价值。希望这篇复盘能帮你少走一些弯路在下一场笔试里把该拿的分稳稳拿到。