面灵AI→

美团 9.19 笔试 十道 AI 选择题与因子数量题

轮次
笔试
时间
2026-09
来源
牛客网

《面试题目》

单选题(10 道,主要与 AI 相关)

  1. 多 Agent 如果要处理共享事实,如何设计?
  2. 长文本的情况下,Transformer-XL 如何处理递归遗忘?
  3. 四个动态分区分配的问题。
  4. 低资源文本翻译任务,在高资源文本完美训练下的模型上 BLEU 值很低,最根本的原因是什么?
  5. Zero-3 加梯度检查点都设计的情况下,还出现 OOM,怎么解决?
  6. KMP 的比较次数。
  7. 二分查找的比较次数。
  8. RLHF 的问题:状态模型和奖励模型训练和目的,PPO 的设计。
  9. 网络地址加子网掩码计算。
  10. ViT 的问题(原帖未完整记录)。

编程题

  1. 给出 n 个数组,问任意两个数相乘后得到的因子数量最大值是多少。
  2. AI Coding 题:通过率从 88.31% 改到 88.52% 就改不动了,被其中的因果图设计卡死。

《参考解析》

多 Agent 共享事实怎么设计:核心是「单一事实源 + 读写协议」。不要让各 Agent 各自维护一份记忆互相覆盖,而是把事实集中放在共享黑板/知识库里,每个事实带上来源、时间戳、置信度和版本号;Agent 通过统一的读写接口访问,写操作走乐观锁或版本号比对,冲突时按优先级或人工确认消解。工程上还要区分「事实」与「推论」——推论必须带出处、可追溯、可撤销;对时效性数据设置过期时间,过期自动降级为待确认;并保留一份变更日志,方便回溯某个结论是基于哪一版事实得出的。如果并发量高,就用消息队列串行化对同一实体的写操作。

ZeRO-3 加梯度检查点仍然 OOM 怎么排查:这两项省的显存不是同一块。ZeRO-3 切分的是参数、梯度和优化器状态,梯度检查点省的是激活值;OOM 说明剩下的开销仍然过大,可能来自:激活重计算的粒度不够(只对部分层做重计算)、micro-batch 或序列长度太大、临时缓冲与通信缓冲(all-gather 的临时区、MoE 的 all-to-all)峰值过高、显存碎片(可用 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True 缓解)、以及未释放的中间变量和日志张量。对应手段:开 CPU/NVMe offload、进一步缩小 micro-batch 并增大梯度累积步数、用序列并行或张量并行摊开激活、对 attention 用 FlashAttention 类实现、检查是否有 .item() 或驻留张量导致图无法释放、必要时增大并行度或换更省显存的优化器(如 8-bit Adam)。回答时把「参数态 / 激活 / 临时缓冲 / 碎片」四类分开算账,比笼统说「调小 batch」专业得多。

RLHF 与 PPO 的组成:RLHF 分三步——SFT 得到初始策略;用人工偏好数据(同一 prompt 的两个回答排序)训练奖励模型,奖励模型通常是带标量输出头的同规模模型,目标是让被偏好的回答得分更高;再用 PPO 在奖励模型给的信号上优化策略。PPO 里通常有四个模型:策略模型(Actor,被训练)、参考模型(Reference,冻结的 SFT 模型,用来算 KL 惩罚防止跑偏)、奖励模型(Reward,提供标量奖励)、价值模型(Critic,估计状态价值用于算优势 GAE)。PPO 的裁剪目标 min(r·A, clip(r, 1-ε, 1+ε)·A) 限制单次更新的策略变化幅度,配合 KL 惩罚抑制 reward hacking;工程上要注意奖励归一化、优势白化、KL 系数调节和长度偏置。

Transformer-XL 的递归与相对位置编码:普通 Transformer 把长文本切成互不重叠的段,段间没有信息流动,而且每段都要从头算,导致长距离依赖丢失且计算浪费。Transformer-XL 引入段级递归:处理当前段时缓存上一段所有层的隐状态(memory),与当前段拼在一起做注意力,梯度不回传到 memory,因此能捕获跨段的长距离依赖;因为拼接后绝对位置编码会冲突(同一位置在 memory 和当前段中有不同含义),它改用相对位置编码,在注意力分数里编码查询与键的相对距离,从根上解决位置语义问题。它并没有「遗忘」,而是把遗忘问题通过跨段记忆缓解;真正需要处理超长上下文时,还得看稀疏注意力、线性注意力或检索增强这些后续路线。

低资源翻译 BLEU 偏低的最根本原因:表面原因是低资源语种数据少,但「在高资源上完美训练的模型」直接拿去测,BLEU 很低最根本的原因是训练与测试的分布不匹配——具体表现为分词/词表覆盖问题:高资源模型的分词器几乎没为低资源语种留下足够的子词单元,该语种的词被切成大量碎片,语义单元被破坏;再叠加语系差异、领域差异和评测集特有的表达习惯,模型即使语法通顺也无法命中参考译文的 n-gram。所以改进方向不是单纯加数据,而是扩展词表并做词表适配、做低资源语种的继续预训练、用回译和双语词典做数据增强,以及在评测侧确认 tokenization 一致(BLEU 对分词非常敏感)。

编程题:两数相乘后因子数量最大:因子个数由质因数分解的指数决定:d(x) = Π(e_i + 1)。把每个数分解成指数向量后,任取两个数相当于把两个指数向量逐元素相加(指数按质数对齐),因此对每个质数取其在前两个数中的指数之和,再乘起来比较大小即可。朴素做法是先对 n 个数各做一次质因数分解(试除到 √x 或用线性筛预处理最小质因子),然后枚举所有数对 O(n²) 合并指数向量求因子数,取最大值。n 较大时枚举会超时,可以做剪枝:只保留因子数最大的前若干个候选(因为乘积的因子数主要受指数分布影响),或者把每个数的指数向量哈希后按质数维度取 top2 指数再合并——不过这类题的稳妥得分点是先把「质因数分解 + 因子数公式」写对,拿到大部分测试点,再优化枚举。注意数值范围:乘法结果和因子数都可能超 int,必要时用 long,因子数本身不需要取模就直接按 64 位算。

选择题里其他考点的关键结论:KMP 的比较次数最坏为 O(n + m)(文本长 n、模式长 m),实际比较次数不超过 2n 量级,因为每个字符最多让 j 前进一次、回退的总量有上界;二分查找对 n 个有序元素的最坏比较次数是 ⌈log₂(n+1)⌉,比较的是中间元素与目标的次数。动态分区分配有四种经典算法:首次适应(从头找第一个够大的空闲区,简单且性能通常最好)、最佳适应(找最小的够用空闲区,容易产生大量小碎片)、最坏适应(用最大的空闲区,剩下的大块还能用)、循环首次适应(从上次位置继续找,分配更均匀)。子网掩码题要用「IP 与掩码按位与得网络地址」,再算广播地址与可用主机数(2^(32-前缀长度) - 2),注意区分「网络地址」「广播地址」和「可用地址范围」三个概念。ViT 的核心是把图像切成固定大小的 patch(如 16×16)线性投影成 token 序列,加位置编码后送进标准 Transformer 编码器,用 CLS token 或池化做分类;关键取舍是 patch 越大序列越短、计算越省但细节损失越多,且 ViT 缺少卷积的局部归纳偏置,因此在小数据集上需要更强的数据增强或大规模预训练才能超过 CNN。