大厂真题 / 百度

百度研发/算法岗笔试备考攻略

百度笔试的难点通常不是偏门模板,而是:在 100 分钟内读准题意、完成建模,并用 ACM 模式一次写对。如果备考时间有限,与其死磕高级动态规划和复杂数据结构,不如先把模拟、贪心、前缀和、排序与基础数学练到稳定得分。

本文整理的是常见校招笔试形态。不同批次、岗位和场次可能调整题量或考查方式,最终以当次考试通知和题面为准。

一、先看考试形态

百度笔试采用 ACM 输入输出模式,常见时长为 100 分钟

  • 研发岗:选择题 + 2 道编程题
  • 算法岗:3 道编程题,并额外考查机器学习相关内容

ACM 模式意味着平台只负责提供标准输入,你需要自行完成读取、求解与输出。平时只写 LeetCode 函数签名还不够,还要熟悉:

  • 单组与多组测试数据的读取;
  • 字符串、数组、矩阵和图的建模;
  • 输出格式、换行与空格;
  • 空数组、单元素、重复值、极值等边界;
  • 根据数据规模判断复杂度,而不是写完后再碰运气。

Python 可以固定使用一份最小模板:

import sys

input = sys.stdin.readline

# 按实际题面读取,下面只演示常用写法
n = int(input())
arr = list(map(int, input().split()))

# answer = solve(arr)
# print(answer)

二、百度更爱考什么

根据已整理真题的题型统计,可把考点优先级概括为:

  • 模拟、思维、构造:约 31%。占比最高,重点是把自然语言规则准确翻译成代码;
  • 贪心:约 21%。排序贪心、区间贪心和局部决策证明尤其常见;
  • 数论与数学:约 13%。相比不少公司存在感更强;
  • 高级 DP 与高级数据结构:合计约 12%,不是短期备考的最高优先级;
  • 哈希表、前缀和、排序、二分答案是贯穿各类题目的基础工具。

这些比例来自历史题目归类,只适合决定复习顺序,不代表某一场考试会严格按比例出题

整体风格更偏向“基础算法 + 细节实现”:题目未必要求最重的模板,但可能在题意转换、边界和复杂度上连续设坑。因此,稳定写对简单题和中等题,通常比只会少量高难模板更有价值。

三、三步备考路线

第一步:保住签到题

先解决“有思路却写不对”的问题:

  1. 练熟 ACM 输入输出与本地调试;
  2. 集中训练模拟、字符串和数组遍历;
  3. 掌握哈希计数、排序、前缀和;
  4. 每道题写完主动检查空集、首尾位置、重复元素与下标边界。

阶段目标:简单题能在 15~20 分钟内独立通过,而不是看题解后觉得自己会了。

第二步:拿下中等题

重点补齐高收益模型:

  • 排序贪心、区间贪心;
  • 二分答案与可行性检查;
  • 双指针、滑动窗口;
  • 位运算;
  • 前后缀分解;
  • 基础构造题。

练贪心不能只记结论。至少要能说清楚:局部选择是什么、为什么不会让答案变差、是否能用交换论证或单调性解释。

第三步:补齐拉分项

按下面的顺序扫盲即可:

  1. 数学/数论:最大公约数、质数与筛法、快速幂、组合计数、模运算与乘法逆元;
  2. 搜索/图论:BFS、DFS、并查集;
  3. 基础 DP:线性 DP、背包的基本状态设计;
  4. 常用数据结构:堆、单调栈。

短期备考不建议从树形 DP、复杂线段树等重型专题开始。先确保前两步能稳定得分,再根据目标岗位和剩余时间扩展。

四、研发岗与算法岗怎么区别准备

研发岗

研发岗不能只刷编程题。选择题需要同步复习岗位基础,具体科目以岗位说明和考试通知为准。常见准备方向包括:

  • 数据结构与算法复杂度;
  • 操作系统、计算机网络、数据库;
  • 所用语言的基础语法、运行机制与常见陷阱。

编程部分则优先覆盖模拟、哈希、前缀和、排序、贪心和二分。目标是选择题不拖后腿,两道编程题至少稳住更有把握的一道,并尽可能获取另一道的部分分。

算法岗

算法岗编程题更多,还需要单独安排机器学习复习时间:

  • 基础概念:偏差与方差、过拟合、正则化、训练/验证/测试集;
  • 经典模型:线性/逻辑回归、朴素贝叶斯、决策树、聚类;
  • 评估指标:Precision、Recall、F1、AUC 等;
  • NumPy 实现:最小二乘、概率计算、常见指标、矩阵运算;
  • 深度学习基础:常见损失函数、Softmax、Attention 的计算流程。

机器学习内容究竟以选择、填空还是编程形式出现,可能随场次变化。不要把“额外考机器学习”简单理解成只背八股;至少要能用 NumPy 写出基础公式,并解释形状和数值稳定性。

五、2025 真题模型拆解

以下只保留题目核心条件,并改写成便于复习的函数练习。由于缺少经官方核对的完整题面,这里不补造输入输出格式、样例或数据范围,也不将它们标记为一套完整 ACM 场次题。

例 1:令人心动——拆分数组的最少操作数

题意(核心版)

给定一个正整数数组。一次操作可以选择一个数,将它拆成两个正整数,且两数之和等于原数。希望经过若干次操作后,所有数中的最大值不超过最小值的 2 倍,求最少操作次数。

思路

设原数组最小值为 m

  • 主动拆分 m 只会产生小于 m 的新数,使允许的最大值上界进一步下降,因此最优方案可以保留 m 不动;
  • 在最小值保持为 m 时,每一块都不能超过 2m
  • 对于原数 x,至少要分成 ceil(x / (2m)) 块;
  • 把一个数分成 k 块需要 k - 1 次二分操作。

这个块数也能构造出来:因为 x >= m,可把 x 分配到上述数量的正整数块中,使每块落在 [m, 2m] 内。因此逐项累加即可。

def min_split_operations(nums: list[int]) -> int:
    """返回满足 max <= 2 * min 所需的最少二分操作数。"""
    if not nums:
        return 0

    m = min(nums)
    limit = 2 * m
    operations = 0

    for x in nums:
        pieces = (x + limit - 1) // limit  # ceil(x / limit)
        operations += pieces - 1

    return operations
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(1)$(不计输入)

常见错误是直接计算 x // (2m),忘记向上取整;或者拆分原最小值,导致基准不断变化,把问题做复杂。

例 2:幸运子串——比较窗口两半的数字和

题意(核心版)

给定一个仅包含数字字符的字符串 s 和一个偶数 k。如果一个长度为 k 的连续子串,其前 k/2 个数字之和等于后 k/2 个数字之和,则称它为幸运子串。统计幸运子串数量。

思路

h = k / 2。先计算第一个窗口的左右半段和。窗口每次右移一位时:

  • 左半和减去离开窗口的旧字符,加上原右半段的第一个字符;
  • 右半和减去这个跨越中点的字符,加上新进入窗口的字符。

每次移动只做常数次运算,总复杂度为 $O(n)$。

def count_lucky_substrings(s: str, k: int) -> int:
    """统计长度为 k、前后两半数字和相等的子串。"""
    n = len(s)
    if k <= 0 or k % 2 == 1 or k > n:
        return 0

    digits = [ord(ch) - ord("0") for ch in s]
    half = k // 2
    left_sum = sum(digits[:half])
    right_sum = sum(digits[half:k])
    answer = int(left_sum == right_sum)

    for start in range(1, n - k + 1):
        middle = start + half - 1
        end = start + k - 1

        left_sum += digits[middle] - digits[start - 1]
        right_sum += digits[end] - digits[middle]
        answer += int(left_sum == right_sum)

    return answer
  • 时间复杂度:$O(n)$
  • 空间复杂度:当前写法为 $O(n)$;若直接用 ord(s[i]) 取值,可降为 $O(1)$ 额外空间

常见错误包括:k 为奇数时仍强行分半、窗口数量少算一个,以及更新右半和时忘记减去跨过中点的字符。

六、100 分钟怎么分配

研发岗:选择题 + 2 道编程题

可以用下面的时间盒作为起点:

  • 0~15 分钟:快速完成有把握的选择题,标记不确定项;
  • 15~20 分钟:浏览两道编程题,判断考点和预期复杂度;
  • 20~50 分钟:先写把握最大的一题,争取完整通过;
  • 50~85 分钟:处理另一题,先拿可实现的部分分,再优化;
  • 85~100 分钟:回查选择题与代码边界,做最后提交。

若选择题数量或权重与预期不同,应按实际题面调整,不要机械照搬。

算法岗:3 道编程题 + 机器学习

  • 0~8 分钟:通读全部题,按“预计得分 / 所需时间”排序;
  • 8~38 分钟:拿下最稳的一题;
  • 38~70 分钟:攻第二题;
  • 70~90 分钟:处理第三题或机器学习内容,优先完成能拿分的部分;
  • 90~100 分钟:检查、补测并完成最终提交。

题目顺序不等于难度顺序。若一道题连续 15~20 分钟没有形成可实现方案,立即切题,避免把整场时间押在一个思路上。

七、最常见的失分点

1. 只刷核心代码,不练 ACM

真正丢分的可能不是算法,而是读错多组数据、漏输出、下标错一位。考前至少做两次完整限时模拟。

2. 只做难题,轻视模拟

模拟题代码不一定短,规则状态多时更考验实现。建议先写状态含义和转移顺序,再动手编码。

3. 忽略数学与数论

最大公约数、快速幂、质数、模运算等单点知识一旦缺失,很难在考场临时推导。它们应当是第三阶段的优先补课项。

4. 贪心只凭直觉,不做证明

样例通过不代表策略正确。写代码前先尝试构造反例,并说明局部决策为何不劣。

5. 算法岗把机器学习留到最后

机器学习公式和 NumPy API 不熟时,现场很难补齐。应当把它作为独立科目穿插练习,而不是传统算法刷完后才开始。

6. 低通过率时盲目重写

先按顺序排查:

  1. 复杂度是否匹配数据规模;
  2. 是否漏了空集、单元素、全相等、极端值;
  3. 是否存在整数溢出(C++/Java 尤其注意);
  4. 多组数据之间的状态是否清空;
  5. 输出格式是否完全一致。

八、时间有限时的复习配比

如果只剩一到两周,可以按以下比例安排:

  • 50%:模拟与基础工具——哈希、前缀和、排序、字符串、ACM 输入输出;
  • 30%:中等题核心——贪心、二分答案、双指针、滑动窗口;
  • 20%:补短板——数论、基础 DP、BFS/DFS、并查集。

算法岗还应从总复习时间中单独切出机器学习练习时间;如果基础较弱,可先按“传统算法 70% + 机器学习 30%”执行,再根据模考结果调整。

最后的验收标准不是刷题数量,而是:

  • 简单题能否在 20 分钟内一次写对;
  • 中等题能否在 10 分钟内识别模型;
  • 能否独立完成 100 分钟 ACM 模拟;
  • 算法岗能否不查文档写出常见 NumPy 计算。

百度笔试的高性价比策略,是先把基础题做稳,再用贪心、二分和数学扩大得分面。 稳定、细心和时间管理,往往比追求少数高难题更重要。