ARTICLE · 998767
美团9月1日机考笔试题与解析
写在前面
本次给大家带来2026年9月1日美团笔试题的3道题,本场机考题目可在咱们平台上在线刷题。
第一题:AI Coding
第二题:选择题
第三题:从指定点出发,按层把三角栈道建成无向图,再用 Hierholzer 算法走出一条每条边恰好走一次并回到起点的回路。
大厂笔试AI Coding练习:CodeFun2000.com/aicoder-gym
第1题-多云成本分摊
题目需求
本题要求交付一个内存型 HTTP 服务:把多云账号费用按版本化分摊方案归集为可审计的成本中心账单。费用按 usageAt 选择已发布版本,沿分摊图递归分配:POOL 按基点权重拆分、余数按 nodeId 字典序补 1;CENTER 归集到成本中心;DELEGATE 跨方案委托;CAP 按 origin period 累计额度、超限分流。方案可追溯发布,系统须按 origin period 重放受影响费用,以"冲销+重述"追加式分录修正历史;批量发布与批量更正整体原子,失败全回滚;已关账账期不可改写,迟到费用与追溯改规落入当前开放期;所有写操作按幂等键去重;且任一时刻满足对账不变量——事件分摊合计等于金额,账期分录净额等于账单净额。
做题步骤
一、榨干题面再动手。 让 AI 通读题目后输出契约清单:全部接口字段、枚举、错误码、排序与过滤规则。强制它把括号里的隐含约束显式化——余数补 1 的顺序、CAP 额度按 (capKey, planId) 共享、批量操作"不得等价为顺序执行多次"等。这些括号句就是判分点,也是 LLM 最爱漏的。
二、规划不可替代的阶段。 与 AI 讨论出约十个缺一不可的阶段:骨架与幂等层、基础实体、账期与时钟、版本校验与环检测、选版逻辑、分摊引擎、费用创建与分录落期、更正与批量更正、追溯发布与重述、关账与对账。重点聊清衔接处:重放的排序键、分录落期的判定函数、重述的触发条件。聊不明白就继续聊,这一步值得花二三十分钟——开工走错方向,后续修正代价远大于规划成本。
三、立机械化规矩。 每次只改当前阶段相关代码;题面有歧义必须停下来问,禁止自行假设;每阶段交付可检验的证据——构造测试用例并跑出实际结果,不接受口头"已完成"。
四、逐条推进,人工 React。 每阶段完成后令其自查边界:权重合计是否严格 10000、列表是否处处字典序、金额是否处处整数分。最小用例验证通过再进下一条。发现它开始输出思维链、左右互搏或改 A 坏 B,立即总结现状、新开会话,守住上下文底线。
五、自测后首提。 重点验证对账不变量和难点场景:关账后的迟到费用、追溯发布引发的跨账号重述、CAP 共享额度下的回放顺序、批量更正的失败回滚。
六、黑盒修正。 提交后把错误信息喂回去,要求列举所有可能原因并逐一构造本地复现,用证据排除。同一方向连续失败,就删掉相关代码、带错误信息新开上下文重写,不在错误路径上打补丁。时间充裕则人眼复核余数分配与 CAP 额度等核心算法,古法 debug 与 AI 修正交替使用,磨到满分。
第2题-选择题
1、仓储调度里用递归函数 weigh(k) 估计堆叠高度为 时的承重分,代码如下。其时间复杂度是?
int weigh(int k) {if (k <= 1) return 1;return (4 * weigh(k - 1) + 5 * weigh(k - 2));}{{ select(1) }}
2、气象站要把逐小时风向记录送进序列模型,比较普通循环网络与长短期记忆网络。下列说法正确的是?{{ select(2) }}
普通循环网络主要用于抽取静态网格图像特征 长短期记忆网络的门控激活普遍采用 ReLU 普通循环网络可以稳定传递很长跨度的依赖 长短期记忆网络用遗忘门、输入门、输出门三组门控来调节细胞状态
3、温室产量建模写成岭回归。观测 ,并给系数先验 。对应的正则化参数 是?{{ select(3) }}
无法确定
4、机房用多卡训练工业点云分割大模型。nvidia-smi 显示 GPU Util 约 ,但 NVLink/PCIe 出流量已经打满。更符合该现象的原因是?{{ select(4) }}
验证步插得过密,额外前向把算力占满却不会打满互联 张量并行把权重切得过碎,跨卡同步把互联带宽占满 未做算子融合,只会让计算更慢,通常不会把 NVLink 打满 日志落盘过密,主要占用 CPU 和磁盘,与 GPU 互联饱和无关
5、告警回放做成链栈,栈顶指针为 hd。新到一帧结点 q,执行 q->next = hd; hd = q;。该操作表示?{{ select(5) }}
仅读取栈顶元素 在当前栈顶之下插入结点 q把结点 q作为新的栈顶压入弹出栈顶元素
6、路面裂缝检测把一个 batch 的图像做成张量,形状为 。对该 batch 做 BN(批标准化)时要算均值和方差。该 batch 中均值和方差的数量是?{{ select(6) }}
7、法规条款编码器做掩码语言模型预训练,希望用数据增强提高每次看到的上下文组合。下列更常被用作这类预训练数据增强的是?{{ select(7) }}
把教师模型的输出蒸馏到学生模型 训练初期把学习率从接近 拉高 动态掩码(Dynamic Masking),每次迭代更换被掩盖的 token 位置 当梯度范数过大时按比例缩小更新步
8、零件入场先进入传送带 ,再转入暂存柱 。 与 初始都为空。零件 pqrstuvw 按该顺序进入 ,每个零件离开 后立刻压入 。若 的出栈顺序是 qsruwtvp,则 的容量至少为?{{ select(8) }}
9、场站用 XGBoost 做设备故障分级。下列说法错误的是?{{ select(9) }}
各轮 boosting 生成的树可以完全并行、互不等待 目标函数加入正则项,用来控制模型复杂度 损失函数用到二阶导数,通常用来提高优化精度 基学习器可以是线性分类器,例如逻辑回归
10、货架盘点序列做希尔排序。以步长 做完一趟后得到 。下列哪一个可能是排序前的原序列?{{ select(10) }}
题解
1
答案:C. 张量并行(TP)通信量过大导致带宽饱和
在千亿大推荐模型预训练场景下,NVLink/PCIe流量饱和,GPU算力利用率低(GPU Util=30%),属于通信瓶颈。张量并行TP会在不同GPU之间频繁交换张量,产生巨大跨卡通信流量,占满通信带宽,GPU等待数据,算力闲置。
梯度累积步数过多:影响的是batch大小,不会直接打满NVLink带宽; GELU内核未融合:属于计算内核慢,瓶颈在GPU计算,不会造成通信饱和; 数据加载NVMe加速:是CPU侧数据IO瓶颈,和NVLink跨GPU通信无关。
2
答案:D. 动态掩码(Dynamic Masking)
动态掩码是BERT类预训练里常用的数据增强手段,每次训练迭代随机对不同位置token做mask,扩充训练样本多样性。
模型蒸馏:是模型压缩/知识迁移,不属于数据增强; 学习率预热:训练策略,调整学习率,不是数据增强; 梯度裁剪:防止梯度爆炸的优化手段,不属于数据增强。
3
答案:D. {4723,1,0,12,7,-9,8,98,36}(原题C、D选项文本重复)
希尔排序增量为,代表把下标相差的元素分为一组,组内进行直接插入排序。 每组元素:下标;下标;下标;下标。一趟希尔排序后,每组内部有序。 对增量分组,原序列分组排序后得到题目给出结果,对比选项只有该选项分组满足一趟增量4希尔排序后的结果。
4
答案:B. LSTM一共有三个门来控制cell state
LSTM包含遗忘门、输入门、输出门三个门控,共同维护cell state细胞状态。
LSTM门控一般用sigmoid,不是ReLU; 原始RNN无法很好处理长期依赖,存在梯度消失; RNN是序列模型,用于时序文本等,不是图像。
5
答案:A. 4
队列Q:,依次出队入栈,出栈序列推演栈变化:
a入栈,b入栈 → b出栈 栈[a] c入栈,d入栈 → d出栈 栈[a,c] c出栈 栈[a] e入栈,f入栈 → f出栈 栈[a,e] e出栈 栈[a] g入栈,h入栈 → h出栈 栈[a,g] g出栈 栈[a] a出栈 栈内同时最多存在共4个元素,所以栈容量至少为4。
6
答案:C. XGBoost支持模型上的并行XGBoost并行是特征维度并行(在分裂节点时并行找最优分割点),不是模型层面并行,
boosting串行生成每一棵树,不能并行训练多棵树,该描述错误。
XGBoost目标函数带L2正则,控制复杂度; 损失使用二阶泰勒展开,利用二阶梯度提升精度; 基学习器可以是线性模型(线性回归/逻辑回归)。
7
答案:B. 插入结点S
链栈头插操作:S->next = P让新节点指向原来栈顶;P=S更新栈顶指针指向新结点S,是栈顶插入新节点。
返回栈顶:只取P,不修改指针; 栈顶下插入:需要修改原有栈顶next; 出栈:P=P->next。
8
答案:A.
递推式:,类似斐波那契递归,递归树节点指数增长,时间复杂度。 每一层产生两个子递归,存在大量重复计算。
9
答案:D. C
BN(BatchNorm),维度,对每个通道C单独计算均值方差。同一通道所有样本、所有空间位置共用一组均值、方差。 一共有组均值与方差。
10
答案:D.
概率视角岭回归:,参数先验贝叶斯推导,最大化后验概率等价最小化:岭回归正则项为,故。
第3题-小美的三角形图游走
题目内容
层台景区把观景栈道按三角形分层铺设。封园前巡检组必须从指定台位出发,把每一段栈道恰好走一遍后再回到起点,才能确认廊道全部可通行。栈道的接法由园方巡检规程固定:同层相邻台位之间有栈道,相邻两层之间再按小三角补上两条斜向栈道。在本题给出的层数范围内,这样的巡回路线一定存在。
巡检区域共有 层。第 层有 个台位,从左到右编号依次为。
当 时,对每个 ,下列三段栈道都存在(无向):
同层相邻:编号为 与 的台位之间; 连向上一层:编号为 与 的台位之间; 另一条斜向:编号为 与 的台位之间。
请给出一条从台位 出发、每段栈道恰好经过一次、并回到 的巡回。若有多种走法,输出任意一种即可。
层数满足 ,出发台位满足 。一次输入中任务数 满足 ,且所有任务的 之和不超过 。
输入描述
第一行一个整数 (),表示随后的巡检任务数量。
接下来 行,每行两个整数 、(,),表示该次任务的层数和出发台位。
保证所有任务的 之和不超过 。
输出描述
对每个任务输出一行,包含 个整数,依次给出巡回经过的台位编号(第一个和最后一个都必须是 )。
若存在多种合法路线,输出任意一种即可。评测会判定路线是否走遍每段栈道恰好一次。
样例1
输入
12 3输出
3 2 1 3说明
只有 2 层,三个台位 1、2、3 构成一个三角形,共 3 段栈道。从 3 出发,依次走 、、,每段恰好一次并回到起点。路径上应有 个编号。
样例2
输入
13 4输出
4 5 2 3 5 6 3 1 2 4说明
3 层共 9 段栈道。从底层左侧台位 4 出发的一条合法巡回是。 相邻编号都是规程里的栈道,且九段各出现一次,首尾都是 4。
样例3
输入
22 24 7输出
2 3 1 27 8 4 5 2 3 5 6 9 8 5 9 10 6 3 1 2 4 7说明
第一项任务只有 2层,从台位2出发,走 即可。第二项任务有 4层、18段栈道,从台位7出发给出一条长为19的巡回;评测只要求每段栈道恰好经过一次,不要求与该输出逐点相同。
题解
解题思路
把台位看成无向图的顶点,栈道看成边。第 层第 个台位的编号是 。对每个 与 c<r同层相邻两点与上一层对应点构成一个小三角形,三条边都要加入图中。
每个顶点的度数都是偶数(角上为 ,边界为 ,内部为 ),图连通,因此存在欧拉回路。 边数是 ,回路上的点列长度为 ,首尾都必须是出发台位 。 从 出发,一直沿着尚未用过的边走;当前点没有剩余边时,把它弹入答案。得到的序列是回路的逆序,再反转即可。 无向边用边号标记删除,避免同一条栈道走两次。邻接表上用指针记下「下一条待看的边」,总复杂度与边数成正比。 任意一条欧拉回路都正确,不需要特定字典序。
复杂度分析
时间复杂度为 (每条边处理常数次)。一次输入所有任务的 之和不超过 ,因此总时间不超过单次 的量级。
空间复杂度为 ,用于邻接表和边表。
代码实现
python代码(C++和JAVA代码见在线OJ网址)
defsolve(h, start):# 台位总数:第 1..h 层分别有 1..h 个点 n = h * (h + 1) // 2 g = [[] for _ in range(n + 1)] eu = [] ev = []defadd(a, b):# 无向边存一次,两端邻接表都记下边号,方便删除(标记) eid = len(eu) eu.append(a) ev.append(b) g[a].append(eid) g[b].append(eid)for r in range(2, h + 1):# base:本层第一个台位的编号减 1;prev:上一层第一个台位的编号减 1 base = r * (r - 1) // 2 prev = (r - 1) * (r - 2) // 2for c in range(1, r): u = base + c v = base + c + 1 w = prev + c# 同层相邻栈道,以及连接到上一层同一个台位的两条斜栈道,构成一个小三角 add(u, v) add(u, w) add(v, w) used = [False] * len(eu) ptr = [0] * (n + 1) stack = [start] circ = []# Hierholzer:一直沿未用边走,走不了时把当前点弹入回路(得到的是逆序)while stack: u = stack[-1]while ptr[u] < len(g[u]) and used[g[u][ptr[u]]]: ptr[u] += 1if ptr[u] == len(g[u]): circ.append(u) stack.pop()else: eid = g[u][ptr[u]] ptr[u] += 1 used[eid] = True a = eu[eid] b = ev[eid] stack.append(b if a == u else a) circ.reverse()return circk = int(input())for _ in range(k): h, s = map(int, input().split()) path = solve(h, s) print(" ".join(str(x) for x in path))