百度2023秋招研发岗笔试复盘:算法与数据结构备考指南
2026/8/29 8:29:25 网站建设 项目流程

2023年秋招季,我坐在电脑前,在浏览器里打开百度研发岗的在线笔试页面,旁边放着两张草稿纸和一瓶水。两个小时的考试,前半段是选择题,后半段是编程题,答题过程中能明显感觉到:这不是单纯刷题就能应付的考试,它更像一次综合能力的筛选。考完之后和几个同样参加秋招的同学复盘,发现这套题在设计上确实有它的章法——知识点覆盖广、代码题难度递进、选择填空题考察得很细。这篇文章就围绕百度2023年秋招研发岗笔试,聊聊我的实际体验、踩过的坑,以及事后总结出来的一套备考思路。无论你是正在准备2024届秋招,还是想了解大厂研发岗笔试的考察逻辑,这篇复盘应该都能给你一些参考。

1. 笔试在秋招链路中的定位:为什么一份代码卷能刷掉大部分人

1.1 简历筛选和面试之间,笔试承担的不只是"筛人"

先理清一个容易被低估的问题:笔试在秋招整体流程里到底扮演什么角色。

投递百度研发岗之后,大部分同学会先收到测评或笔试链接。简历筛选自有 HR 和业务线的规则,但笔试更像一个"标准化考试",它的价值在于用同一套题目在同一个时间窗口内横向对比所有候选人。简历里的项目经历可能注水,实习经历可能包装,但代码题对不对、边界条件想没想到、时间复杂度过不过得去——这些在在线评测系统里一测便知。所以笔试承担的核心功能是"卡基准线":筛选出代码能力扎实、基础概念清晰、具备基本解题思维的人。

我有位同学秋招投了二十多家公司,简历关几乎一路绿灯,但最后拿到的面试邀请寥寥无几。后来查了下记录,发现好几家都是在笔试环节就被沉了。这件事给我最大的提醒是:研发岗的简历写得再漂亮,笔试不过线,后面的一切都无从谈起。

1.2 与其他公司笔试题相比,百度的出题风格有什么特点

横向对比过几家大厂的研发岗笔试题之后,我觉得百度的出题风格有几个比较明显的特征。

第一,难度梯度做得比较清晰。题目不是从头难到尾,而是由易到难排列,前面的选择题甚至有几道属于"送分题",比如数据结构基础、排序算法复杂度、TCP 握手过程这类计算机基础知识。这样的设计意图很明显:先保证基础扎实的人能拿到基本分,再通过后面的编程题拉开区分度。第二,编程题注重考察"常见算法的灵活变形",而不是直接出模板题。直接套模板往往过不了,需要根据题目条件做额外处理。第三,部分题目带有业务色彩,题干可能会包装成搜索、推荐、地图导航这类实际场景,本质上就是在考算法,但阅读量更大,对理解题意能力提出了更高要求。

1.3 笔试得分怎么影响后续流程

很多人以为笔试只是及格和不及格的区别,实际上不是。在百度这类大厂的招聘系统里,笔试成绩往往会伴随你的整个面试流程。面试官能在系统里看到你的笔试得分和解题详情,甚至能翻看你提交的代码。如果笔试成绩够高,面试时你有机会被问到更多加分项问题,考察重点也从"基础行不行"转向"潜力大不大";如果笔试成绩低空飘过,面试官往往会挑着你的弱项往深处问,相当于给简历上的技术画像打个底。

所以我给所有准备秋招的同学一个建议:笔试不要抱着"过了就行"的心态,能多拿一分是一分,尤其是编程题,尽量做到提交的代码逻辑整洁、注释清晰。有些面试官真会看你的答题代码——我和朋友在面试时就遇到过,面试官指着笔试系统里我提交的代码说:"你这题当时的思路记录挺清楚的,来说说为什么用二分而不是哈希?"

2. 卷面拆解:考试构成、知识点分布与时间分配的实测复盘

2.1 题型构成和大致占比

以我实际参加的场次为例,整个笔试卷面大致分为三个部分:单选题、多选题、编程题。选择题加起来大概占总成绩的一半,编程题占另一半。具体分值比例每年可能有调整,但大方向不会变——代码能力始终是重头。

选择题的内容覆盖范围比较宽,这也是很多同学觉得"复习不过来"的原因。从考点来看,主要有这几块:

  • 数据结构:栈、队列、二叉树遍历、散列表冲突处理、堆和优先队列的复杂度
  • 算法基础:排序算法稳定性、二分查找边界、贪心算法的适用条件、动态规划的判断
  • 操作系统:进程与线程、死锁条件、虚拟内存、页面置换
  • 计算机网络:TCP/UDP、HTTP 状态码、DNS 解析过程、拥塞控制
  • 数据库:事务隔离级别、索引的结构、SQL 的基本写法
  • 编程语言特性:C++ 的内存管理、Java 的集合类、Python 的 GIL 这类语言相关的细节

这部分没有太多"刁钻"的题,但胜在范围广。如果只看算法题、不看基础概念,很容易在这上面丢分。我认识的不少朋友,刷题刷得很猛,但一到操作系统和网络的选择题就开始犹豫,最后笔试成绩被硬生生拉下一个档位。

2.2 编程题的难度分布和常用算法

编程题一般有 3 道左右,难度逐题递增。第一道通常是基础题,例如数组遍历、字符串处理或者简单模拟,考查的是基本的编码能力,确保你能够把思路快速转成代码。第二道会在基础之上加一些弯,可能是二分答案、贪心设计、前缀和优化或者经典 DP 的变体。第三道往往涉及图论、搜索、复杂状态 DP 或数据结构组合,比如栈加贪心、堆加排序这类复合型题目,用来拉高区分度。

从算法角度来说,以下几类在笔试中尤其需要重点准备:

  • 二分查找及二分答案,尤其是"最小值最大/最大值最小"这类套路
  • 动态规划:线性 DP、背包 DP、区间 DP、状态压缩 DP 的经典模型
  • 图论搜索:DFS、BFS、拓扑排序、最短路径(Dijkstra 优先队列版)
  • 数据结构进阶:并查集、树状数组/线段树、单调栈、单调队列
  • 字符串处理:模式匹配、回文、子串计数

2.3 时间分配策略:怎么保证选择题和编程题两头兼顾

秋招笔试的时间通常是 120 分钟,看起来不短,但真正分配起来其实很紧张。我的建议是:选择题控制在 40 分钟以内,绝不超过 45 分钟;剩下的时间全部留给编程题。选择题可以用一些"快速排除法"——分析四个选项的差异点,找到关键条件后直接判定,不必把每个选项都验算一遍。如果遇到某个知识点确实不熟悉,凭第一感觉选一个然后立刻标记跳过,千万不要在一道题上死磕五分钟。

编程题的时间分配也有技巧。拿到题目后先看一遍三道题的题干,大致判断难度,从最有把握的那道开始做。哪怕第一题最简单,也先花一分钟理清输入输出格式,再动手写代码。如果遇到一道题 20 分钟还没有思路,果断止损,去写其他题,最后有时间再回头补。笔试环境里的代码编辑器很朴素,没有智能提示,写代码的速度和准确率完全靠平时积累,所以平时练习时最好直接用命令行或简单编辑器,不要过度依赖 IDE。

3. 高频考点的底层逻辑:为什么笔试偏爱这些知识

3.1 数据结构:不只考"是什么",更考"怎么选"

应付百度这类大厂的笔试题,数据结构不能只停留在"能写出遍历和查找"的层面,更重要的是理解每种结构的适用场景和复杂度边界。

举个例子:一道题如果涉及频繁的"查询区间最小值"和"动态修改单个元素",你第一反应应该是线段树或树状数组,而不是每次查询都重新遍历。因为笔试的测评数据往往会把时间复杂度逼到极限,普通做法只能过掉前几个小数据点。又比如,括号匹配、表达式求值这类问题天然适合用栈;滑动窗口求最值就上单调队列;元素去重和快速判断是否存在用哈希表;维护前 K 大就用大小为 K 的小顶堆。

我看到不少同学在复习时陷入一个误区:把每种数据结构的实现代码背得滚瓜烂熟,但拿到一个新题时不知道用哪种结构。关键在于"场景识别"。建议平时刷题时不要只按题目标签刷,而是多做"不告诉你知识点"的题,训练自己在题目描述里定位到合适数据结构的敏感度。

3.2 动态规划:从"背模板"到"定义状态"

动态规划是百度研发岗笔试里几乎必考的内容,要么单独出一道题,要么作为编程题里某个部分出现。DP 题的本质是"用已知状态推导未知状态",核心有三件事:状态定义、状态转移方程、边界条件。很多同学觉得 DP 难,是因为拿到题之后想的不是"我从哪里来"或者"我能到哪里去",而是想套用之前做过的某道题的模板,比如"这像 0-1 背包,我就用背包模板"。

但大厂的 DP 题往往不是原题。它会在经典模型上做变形:可能是物品有额外属性,可能是背包容量范围特别大需要剪枝,可能是转移时要用到前缀和优化。这时候,如果你只记住了模板而没理解状态定义的本质,大概率会写出一个"看起来对但样例过不了"的代码。备考 DP 时,更重要的是亲手把每道经典题的转移方程推导一遍,弄懂为什么状态数组开这么大,为什么初始化是这个值,为什么转移顺序是从前到后。理解了这三点,遇到变形题才能从容应对。

3.3 搜索与图论:BFS/DFS 的选择直接影响通过率

搜索类题目在百度往年笔试中同样有较高的出现频次。尤其是 BFS 求最短路径、DFS 求连通性和回溯搜索,几乎每场都有涉及。BFS 和 DFS 本身不难实现,但它们在题目中的应用有一些容易忽略的细节。

比如 BFS 求最短步数时,除了维护队列,还需要一个 visited 数组来避免重复入队,否则复杂度呈指数增长。如果图特别大,可以考虑双向 BFS 或优先队列 BFS。又比如 DFS 做回溯时,撤销状态的顺序和路径选择必须一一对应,否则会出现状态污染,导致答案错误。这些细节在笔试中特别容易翻车——因为样例数据往往很小,你的错误路径可能恰好也能跑出正确结果,交给评测机的大数据一测就崩。

图论里还需要关注拓扑排序。拓扑排序的应用场景很多:判断有向图是否存在环、任务调度、依赖关系问题。它和 BFS 的区别在于利用了入度作为约束条件,代码模板很短,但很实用,建议熟练掌握。Dijkstra 优先队列版本也是常客,尤其是当题目伪装成"地图导航""路线规划"这类业务场景时,本质上都是最短路问题。

3.4 思维题和"读代码"题:防不胜防但可以用系统化方法应对

除了算法和数据结构的常规考点,百度笔试里偶尔也会出现一些"思维题"或者"读代码题"。前者常常以数学技巧、双指针、贪心策略为背景,后者则是给一段代码,让你判断输出结果、找出 bug 或者分析复杂度。这类题其实并不需要特殊的赛题知识,关键是平时养成"审题先行、举例验证"的习惯。遇到抽象的描述,先手写一两个小样例,把输入输出跑一遍,很多时候答案就自然浮现了。

读代码题更是如此。不要盯着代码一行行空想,直接在草稿纸上模拟几个输入,逐步跟踪变量变化。尤其要注意循环退出条件和变量累加顺序,这两处是出题人最喜欢埋雷的地方。

4. 在线笔试环境里的实战避坑:从输入输出到边界条件

4.1 输入输出格式:第一只拦路虎

在线笔试和本地 IDE 跑代码最大的区别就是输入输出格式完全由题目控制。很多第一次参加笔试的同学会在这一步骤上浪费大量时间。百度笔试系统通常支持多种语言环境,以 C++、Java、Python 为主,评测机会自动调用你的程序,把测试数据作为标准输入喂进去,校验标准输出。这里最忌讳的就是自己写"请输入一个数"这类的提示语句,评测机会把提示也当成输出的一部分,结果全错。

多行输入的读取方式也要注意。Python 里常见的坑是input()读取字符串后忘记去掉末尾换行,或者用split()切分出空字符串。如果题目没有明确给出数据行数,通常需要用while True+try/except循环读取直到 EOF。Java 里则要注意ScannernextLine()nextInt()混用时的换行问题——建议读完数字后单独再nextLine()一次把残留换行消费掉。C++ 用cin相对安全一些,但要注意getline()cin混用时的缓冲问题。

4.2 样例通过不等于能全过:边界条件才是真正的分水岭

在线评测系统一般会给一个题目样例,样例通过了,往往意味着主流程正确,但评测数据里还包含大量边界数据:空数组、数组长度为 1、全部值相同、值取到 int 上限、负数、字符串长度为 0 等等。这些边界条件才是拉开分数差距的关键。

以最大子段和为例,如果数组全是负数,经典 Kadane 算法的返回值应该是最大的那个负数,而不是 0,如果初始化max_sum = 0,就会在全是负数的测试数据上栽跟头。再比如二分查找,如果输入数组长度为 1,左右指针的初始值和中点计算公式必须保证不越界。这些细节在平时练习时很容易被忽略,因为样例通常都是常规数据。考前最后一周,刷题时一定要刻意训练自己"每写完一个算法就立刻问:边界上会发生什么"。

4.3 时间复杂度与内存限制:过了样例却被判超时,怎么办

笔试系统通常会限制单题时间(比如 1 秒)和内存(比如 256 MB)。如果你的解法复杂度是 O(n^2) 而题目给定的 n 是 10^5,超时就不可避免。遇到超时,最优先的思路是:把当前解法的时间复杂度降一个量级。

常见的优化手段包括:用哈希表把查找从 O(n) 降为 O(1);用排序加双指针替代双重循环;用前缀和把区间求和变成 O(1) 查询;用二分答案把优化问题转成判定问题;用 BFS/DFS 剪枝降低搜索空间。如果代码确实已经优化到最优复杂度但仍然超时,那可能是常数太大,可以试试关闭同步流(C++ 的ios::sync_with_stdio(false))、用更快的输入输出方式、避免在循环里重复创建对象。

内存超限相对少见,但一旦出现也很头疼。常见原因是递归深度过大导致栈溢出(Python 尤其明显),或者数组开得过大却只用了很小一部分。递归过深可以改用显式栈模拟,数组过大的话优先考虑滚动数组或状态压缩。

4.4 本地运行正常但提交后编译失败:语言细节的坑

在线笔试的过程里还有一个特别让人抓狂的情况:在本地 IDE 里跑得好好的,复制到答题框里一提交,提示编译错误。常见原因有几个:Python 写的代码里用了中文标点或者全角括号;Java 的类名没有按系统要求命名为Main;C++ 用了本地特有的头文件或编译器扩展(比如<bits/stdc++.h>在某些环境可能不受支持)。还有一个很隐蔽的坑:代码里用了 Python 3 的语法特性,但评测环境是 Python 2 的。提交前,一定要留意系统支持的语言版本。

5. 编程题复盘:三道典型题目从思路到代码的完整推演

5.1 典型题一:数组区间处理——前缀和 + 哈希表

先来说一道典型的"看似简单但很容易超时"的数组题。题目大意是:给定一个整数数组,找出和为某个目标值的连续子数组的个数。最暴力的做法是二重循环枚举所有区间,复杂度 O(n^2),如果 n 是 10^5 那么大,超时是必然的。正确思路是用前缀和配合哈希表:把前缀和存入哈希表,在遍历过程中维护"当前前缀和减去目标值"在哈希表中出现的次数,累加进答案。

这种题考察的是两个经典技巧的叠加:前缀和用于快速计算区间和,哈希表用于把"是否存在"和"出现次数"的查询降到 O(1)。代码本身很短,十几行就写完,但如果对前缀和思想不熟,可能会在暴力解上浪费大量时间。我当时的做法是用 Python 写的,代码如下:

from collections import defaultdict def subarray_sum(nums, k): prefix_sum = 0 count_map = defaultdict(int) count_map[0] = 1 # 前缀和等于0的情况初始化,有助于处理从开头开始的子数组 ans = 0 for num in nums: prefix_sum += num ans += count_map[prefix_sum - k] count_map[prefix_sum] += 1 return ans

这里最需要注意的就是count_map[0] = 1这一行。如果没有它,从数组头部开始的子数组会被漏掉。这种细节,也是评测数据里最容易藏雷的地方。

5.2 典型题二:动态规划与空间优化——一维滚动数组

第二类高频题是背包类 DP 的变体。比如有一类题目是:给定若干物品的重量和价值,背包容量为 W,求能装下的最大价值。经典 0-1 背包的状态转移是dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]),但二维数组在容量很大的时候很浪费空间,所以实际答题时通常要改成滚动数组。

注意 0-1 背包和完全背包在滚动数组下的遍历顺序完全不同。0-1 背包要求每个物品最多选一次,所以内层循环必须从大到小遍历容量;完全背包则相反,从小到大遍历。很多考生在这里翻车,就是因为没理解滚动数组之所以要倒序遍历,是为了保证每个物品只被使用一次。代码模板如下:

def knapsack_01(weights, values, capacity): dp = [0] * (capacity + 1) for i in range(len(weights)): for w in range(capacity, weights[i] - 1, -1): dp[w] = max(dp[w], dp[w - weights[i]] + values[i]) return dp[capacity]

笔试中遇到这类题,千万别急着写代码,先在草稿纸上确认:这是 0-1 背包还是完全背包?物品可不可以重复选?容量范围有多大?需不需要用位运算或者单调队列优化?把这些问题想清楚了再动键盘。

5.3 典型题三:图上的搜索——BFS 求最短路径的变形

第三道编程题通常开始上难度,BFS 求最短路径是一个经典的方向。但是笔试题不会那么老实地告诉你"求这个图里某点到某点的最短路径长度",它会把 BFS 包装成各种场景。比如:在一个二维网格里,从起点走到终点,途中有些格子有障碍物,最多可以拆除 k 个障碍物,求最短步数。这个题的难点在于同样一个格子,拆除不同数量的障碍物后访问它,后续状态是完全不同的,所以 visited 数组不能只记坐标,要记(x, y, 剩余拆除次数)三元组。

BFS 的状态设计是图论搜索题的核心。状态设计好了,代码就是标准的队列扩散;状态设计漏了一个维度,答案直接错误。还有一个容易忽略的点是 BFS 的层序问题:如果每次循环只弹出一个节点,需要记录当前的"层深度",推荐使用普通队列配合步数数组,或者每轮循环通过queue_size = len(queue)来逐层处理。以下是我的写法:

from collections import deque def shortest_path(grid, k): rows, cols = len(grid), len(grid[0]) # visited[x][y][k] 记录是否访问过 visited = [[[False] * (k + 1) for _ in range(cols)] for __ in range(rows)] q = deque() q.append((0, 0, k, 0)) visited[0][0][k] = True directions = [(1, 0), (-1, 0), (0, 1), (0, -1)] while q: x, y, rest, steps = q.popleft() if x == rows - 1 and y == cols - 1: return steps for dx, dy in directions: nx, ny = x + dx, y + dy if 0 <= nx < rows and 0 <= ny < cols: if grid[nx][ny] == 0 and not visited[nx][ny][rest]: visited[nx][ny][rest] = True q.append((nx, ny, rest, steps + 1)) elif grid[nx][ny] == 1 and rest > 0 and not visited[nx][ny][rest - 1]: visited[nx][ny][rest - 1] = True q.append((nx, ny, rest - 1, steps + 1)) return -1

这道题给我的教训是:BFS 的队列里存的信息一定要"完整且最小"。存了多余信息会浪费内存,存少了会导致状态丢失。写完代码后,我习惯在本地跑两个用例:一个是最简单无障碍的图,另一个是所有格子都有障碍物的图,专门验证rest的消耗逻辑。

5.4 复盘时看的不是答案,而是"卡住的位置"

笔试结束后,很多人第一件事是找答案对得分。但我更推荐另一个复盘方法:找一道当时没做出来的题,重新在本地实现一遍,记录自己卡住的位置。是理解题意用了太久?是状态转移想不到?是边界条件没考虑全?还是代码 bug 太久没定位出来?每一类卡点,对应的备考策略完全不一样:理解题意慢,就多看题、多做长题干模拟;状态转移想不到,就专门练 DP 和搜索的套路;边界条件漏,就养成写代码前先列输入输出的习惯。只有把卡点定位准确,下一次笔试才不会在同一类问题上浪费时间。

6. 笔试之后:如何把这份经历转化成面试的竞争力

6.1 笔试做得好,面试时可以主动利用的机会

笔试成绩高,在面试环节是有隐形加分的。有些面试官会当场打开你的笔试记录,问你这道题当时的思路。如果你能清晰地复述题目、解题思路、复杂度分析,甚至指出自己当时代码里的小瑕疵,面试官对你的好感会明显上升。这等于你在面试还没开始前,就获得了一个相对轻松的技术展示窗口。

所以,笔试结束后不要立刻把题目忘掉。建议找时间把当时没做出来的题目和做出来但有疑问的题目重新整理成一篇题解笔记。不是为了发博客,而是为了面试时能够流畅地讲出来。面试官通常更关注你的思考过程,而不是单纯地记忆答案。

6.2 根据笔试暴露的薄弱点,倒推面试复习优先级

笔试结束后,对照卷面做一次"弱点清单"整理很有必要。比如选择题错了操作系统相关的知识点,那就把进程管理、内存管理、死锁这些内容重新过一遍;编程题卡在 DFS 剪枝上,那就集中刷一周搜索类题目;读代码题踩了循环条件判断的坑,那就多练习手写模拟代码执行过程。笔试暴露的问题通常也是面试时会遇到的问题,因为大厂的面试官同样看重计算机基础和数据结构的理解。提早把这些薄弱点补上,对后面的面试帮助巨大。

6.3 秋招是一个长跑,笔试经验是可以复用的

百度研发岗笔试带给我的,不只是一次通过与否的结果,更是一套"如何系统备战大厂笔试"的方法。这套方法在之后参加其他公司的笔试时也一直在用:先拆题型,再定时间,然后按难度梯度答题,遇到卡壳果断跳过,最后集中检查边界条件。不同公司的题风格有差异,但核心考察的能力是相似的:算法思维、编码实现、基础知识的熟练程度。把这些能力练扎实了,后面的每一场笔试都会轻松很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询