
每年春招笔试季美团研发岗的题目都会在求职社区里被反复讨论。2026.03.14 这场也不例外——题量不算大但信息密度很高好多同学出了考场的第一反应是“题目都见过就是没做对”。我按社区回忆和面经复现了一份还原度较高的题目版本逐题写了推导过程和参考实现。这篇文章适合两类人看一类是正在备考大厂笔试、想摸清美团出题风格的同学另一类是算法刷了很多却总在笔试现场卡壳的选手。看完你应该能明显感觉到美团研发岗的笔试重点其实非常集中算法题永远套着业务场景的壳基础题永远落在网络、OS、数据库这几个老考点上场景题总绕不开外卖、配送、商家这套基本盘。1. 先拆这套题的底牌题型分布与美团式出题套路美团研发岗笔试和字节、阿里不太一样的地方在于它很少出那种偏门冷门的算法题几乎每一道都能在力扣上找到原型但如果你只是背过题解、没理解内核套上业务背景之后就容易懵。这套题整体结构大致如下。题型数量核心考点难度单选/多选15道左右TCP、HTTP、进程线程、B树、HashMap中等偏易编程题核心3道扫描线、DFS/BFS、单调栈中等偏难业务场景设计1道状态机、接口设计、降级方案中等从分值占比看算法题是绝对大头三道题差不多占了总分的60%以上。从考点分布看美团特别喜欢做一件事给经典算法换一层业务包装。比如“配送员的接单时间区间”本质是区间重叠问题“组织架构层级”本质是树的深度遍历“空闲骑手分布区域”本质是最大全1矩阵。这种出题方式的潜台词是光会默写模板不够你得能识别出题目背后的算法模型。备考思路也要跟着调整。很多人刷题喜欢按标签刷比如一周专门刷动态规划一周专门刷图论但美团的题目往往是“数据结构标签”和“业务场景”混着来。我建议按题型背后的思想去刷扫描线、差分数组、单调栈、树的遍历这几类出现频率最高务必做到能闭眼写出模板。另外美团笔试题里经常留一个“一眼能读懂、一做容易错”的细节坑比如区间开闭、数组下标从0开始还是从1开始、数据范围是不是超过int这些在复盘时我会逐个点出来。2. 编程题拆解上配送时间区间合并与组织架构树两道“业务壳经典核”的送分题这套题的前两道编程题相较最后一道压轴题温和不少但恰恰是这种“温和题”最容易因为读题不仔细丢分。我先还原题目再讲推导最后给参考代码。2.1 第一题外卖骑手最少需要多少人——区间重叠问题的最优解题目大意是给定n个配送任务每个任务有一个开始时间和结束时间同一个骑手同一个时间段内只能执行一个配送任务问至少需要多少骑手才能覆盖全部任务。输入形式是二维数组比如[[1, 3], [2, 5], [4, 6]]输出最少骑手数。这道题的本质就是求区间最大重叠数。区间重叠是笔试高频题解法有几种排序后用小顶堆维护结束时间、扫描线事件统计、差分数组。美团这道题因为时间点是离散可枚举的用扫描线最直观——把每个开始时间记作1事件每个结束时间记作-1事件按时间顺序累加过程中的最大值就是答案。一个容易错的点是区间开闭。如果题目说“结束时间之后可以接新任务”那[1,3]和[3,5]可以共用一个骑手对应代码里结束时间事件应该延到3这个点才开始减。如果题目说“两个区间重叠”默认左闭右开是常见约定。我按左闭右开来写也就是结束时间点本身不占骑手。参考实现如下。#include bits/stdc.h using namespace std; int minCouriers(vectorvectorint tasks) { mapint, int events; // 时间点 - 净增骑手数 for (auto t : tasks) { events[t[0]]; // 开始骑手占用 1 events[t[1]]--; // 结束骑手释放 -1 } int cur 0, ans 0; for (auto [tm, delta] : events) { cur delta; ans max(ans, cur); } return ans; }复杂度O(n log n)主要花在map排序上。这里有几个实操细节值得说。第一用map而不是unordered_map因为你必须按时间顺序扫描直接用map省去手动排序。第二如果任务时间范围很小且确定可以用差分数组把复杂度降到O(n T)但笔试场景下map就够了不要过度优化。第三这题有个常见变体是让你输出“哪个时间段最忙”那就在累加过程中同时记录cur最大的时间区间即可逻辑完全一样。2.2 第二题找出组织架构里最深的一条汇报链——树的深度与路径还原第二道编程题给了一张员工组织架构表每个员工有唯一编号和直属上级编号上级为-1表示根节点CEO。要求输出从根节点到最深叶节点的完整路径长度和路径本身。本质上是一棵多叉树求最大深度并打印一条最长路径。这题考的是DFS和路径回溯。最稳妥的做法是先把parent数组转成邻接表即children列表然后从根开始往下搜索。注意题目没说输入一定是按顺序的所以要先扫一遍找根再建表。路径还原的关键点是不要只存最大深度要在递归过程中维护当前路径当发现当前路径更长时就拷贝一份作为答案。#include bits/stdc.h using namespace std; vectorvectorint children; vectorint curPath, bestPath; void dfs(int u) { curPath.push_back(u); if (curPath.size() bestPath.size()) { bestPath curPath; } for (int v : children[u]) { dfs(v); } curPath.pop_back(); } int main() { int n; cin n; vectorint parent(n); children.assign(n, {}); int root -1; for (int i 0; i n; i) { cin parent[i]; if (parent[i] -1) root i; else children[parent[i]].push_back(i); } dfs(root); cout bestPath.size() \n; for (int i 0; i (int)bestPath.size(); i) { if (i) cout - ; cout bestPath[i]; } cout \n; return 0; }这题有几个隐藏的坑需要注意。第一树的递归深度可能很大如果组织架构退化成一条链比如n10万函数递归会爆栈。笔试环境里C默认栈空间不大稳妥起见可以把DFS改成显式栈路径记录或者用递推从每个节点向上走并把路径反转。第二路径变量在递归中必须回溯pop_back这是最常见的出错点。第三如果有多条相同深度的路径题目一般要求输出任意一条所以“”和“”要看清用“”会比较稳。3. 编程题压轴空闲骑手最大矩形区域——单调栈思维才是大招第三道编程题是这套卷子里区分度最大的一道。题目大意是运营给了一张网格地图每个格子标记为1表示该区域有空闲骑手0表示没有现在要找一块全为1的矩形区域使得它能容纳最多空闲骑手输出最大面积。这就是经典的“最大全1子矩阵”问题力扣85题。很多同学第一反应是用二维前缀和暴力枚举所有矩形复杂度O(m²n²)m和n一旦过百就完全跑不动。这道题正解是单调栈转化过程分成两步第一步对每一行计算高度数组h[j]h[j]表示从当前行往上数连续的1的个数第二步把每一行的高度数组当成柱状图用单调栈求柱状图里最大矩形的面积。两步合起来复杂度O(mn)这是最优解。为什么高度数组能转成柱状图因为某个矩形若能扩展到当前行它的高度受限于列方向上连续1的最小高度而这个最小高度在“柱状图最大矩形”问题里就是柱子的高度瓶颈。逐行扫描时每新增一行我们就重新计算每个位置向上能延伸多少个1然后求当前这组柱子能框出的最大矩形。整个过程可以理解为把二维问题拆成m个一维问题逐一击破。#include bits/stdc.h using namespace std; int largestInHistogram(vectorint h) { h.push_back(0); // 哨兵强制清空栈 stackint st; int res 0; for (int i 0; i (int)h.size(); i) { while (!st.empty() h[st.top()] h[i]) { int height h[st.top()]; st.pop(); int left st.empty() ? -1 : st.top(); res max(res, height * (i - left - 1)); } st.push(i); } h.pop_back(); return res; } int maxFreeRiderRect(vectorvectorint grid) { if (grid.empty() || grid[0].empty()) return 0; int m grid.size(), n grid[0].size(), ans 0; vectorint height(n, 0); for (int i 0; i m; i) { for (int j 0; j n; j) { height[j] grid[i][j] 1 ? height[j] 1 : 0; } ans max(ans, largestInHistogram(height)); } return ans; }这里我重点说一下单调栈代码里的两次容易出错的地方。第一为什么在while循环里取left要用“st.pop()之后再看栈顶”因为栈中存的都是严格递增的下标当前元素h[i]一旦比栈顶矮栈顶这个柱子能扩展到的最远左边界是它下面那根柱子的右侧位置即st.top()这个下标刚好是当前被弹出柱子的左边界。第二为什么计算宽度用i - left - 1而不是i - top因为i是不包含当前柱子的右边界左边界left也不包含两者之间隔着(i - left - 1)个格子这个细节错一个单位整个答案就错。压轴题最考验的不是单调栈的模板而是你能不能现场把“柱子宽度”和“网格坐标”这两个抽象层的映射关系理清楚。我实测下来这道题在笔试现场的最优策略是先花两分钟确认能否用动态规划暴力解m、n都小于等于200时前缀和O(m²n²)肯定不行但O(mn)的单调栈一定行然后直接写单调栈版本。如果时间紧张可以先写出O(mn)的逐行转化再用栈优化。4. 计算机基础题网络、OS、数据库里易错易混的高频考点美团研发岗的基础题不走偏门选择题考点非常经典但会在选项上做文章专门挖你“学了个大概”的脑补理解。我把这套题里最典型、也最容易丢分的几个点整理出来边回忆题目边讲原因。4.1 TCP三次握手的后续处理第三次握手的ACK丢了怎么办这题几乎每年都出现。正确答案是连接照样建立但服务端会认为连接未建立定时重传SYNACK直到超时。很多同学错在认为“ACK丢了连接就失败”实际上客户端已经进入ESTABLISHED状态服务端重传SYNACK时客户端收到后会忽略因为它已经有连接上下文若重传超过一定次数服务端才主动释放半连接。这个机制背后是“两次握手不可靠第三次握手只是为了让服务端确认客户端收到了自己的序列号”丢了就要靠重传兜底。笔试遇上不要凭直觉选要站在“谁的状态先变化”的角度推理。4.2 进程、线程、协程到底谁切换成本最低美团这道选择题给了三个场景CPU密集型任务、I/O密集型任务、高并发短连接分别让你选合适的调度单位。核心考点是协程切换发生在用户态不涉及内核态所以切换成本最低线程切换要陷入内核进程切换不仅要切换上下文还要切换地址空间成本最高。对于I/O密集型任务协程的“遇到阻塞自动让出”能力能极大提升吞吐。易错点是把协程当成“不需要操作系统调度”就认为它不能利用多核——协程本身跑在线程上你要的是线程池协程的组合这个点题目有时会作为干扰项。4.3 数据库为什么索引默认用B树而不是哈希索引这题在美团笔试里出现频率极高而且选项设计得很阴。哈希索引确实在等值查询上O(1)但一旦遇到范围查询、排序、前缀匹配就全部失效。B树的优势是三件事叠加叶子节点有序天然支持范围查询和排序非叶子节点只存键不存数据单节点能存更多索引项树更矮磁盘IO次数少叶子节点用链表串联全表扫描和范围扫描非常顺滑。另一个常被问到的点是为什么不用红黑树或跳表——红黑树在内存里效率高但磁盘IO次数多跳表在工程上实现复杂且缓存不友好。回答这类题的思路是不要只背结论要同时说清楚“磁盘IO模型下树高决定了一次查询要读几页数据”。4.4 MySQL的MVCCReadView到底在解决什么问题美团基础题里再次出现MVCC可见性判断。核心考点是事务隔离级别中的RR可重复读和RC读已提交都依赖ReadView但生成时机不同。RR在第一次查询时生成ReadView直到事务结束所以同一个事务里的多次查询看到一致快照RC每次查询都重新生成ReadView所以能看到别的事务新提交的数据。当你遇到“为什么在RR隔离级别下A事务读不到B事务已提交的数据”这类问题时答案不是加锁而是ReadView里的活跃事务数组把B的trx_id挡在了外面。这里最容易混淆的点是把MVCC和当前读、快照读搞混题目会故意说“某条update语句读不到其他事务数据”其实是当前读加了锁和你以为的快照读是两码事。4.5 HTTP/2多路复用为什么还有人提队头阻塞这道题问的是HTTP/2引入帧和多路复用后队头阻塞问题是否彻底消失答案是否定的。HTTP/2在应用层解决了HTTP/1.1的队头阻塞一个连接里的请求可以并行传输但底层TCP如果丢包TCP的拥塞控制会阻塞整个连接所有流这叫传输层队头阻塞。美团还喜欢顺带考HTTP/2的头部压缩和二进制帧格式。复习时抓住一个主线HTTP/1.1问题是串行HTTP/2问题是TCP不可靠引发的阻塞HTTP/3用QUIC把连接移到UDP上才是真正对症。5. 业务场景设计题外卖订单状态机与“附近推荐”接口这类“软硬结合”题怎么答美团研发岗的笔试和面试有一个很大的不同笔试里的场景题不需要你写完整代码但要求思路完整、边界考虑充分。这套题出了两道场景简答一道是“设计外卖订单状态机”一道是“设计首页附近推荐接口的排序逻辑”。这两题分值不高却特别能体现一个人的工程思维。5.1 外卖订单状态机把正常流转和异常分支都写清楚题目会让你罗列订单从创建到完成的所有状态并说明每个状态下可以发生哪些事件、不能发生哪些事件。我习惯用“状态 事件 动作 目标状态”的表格来组织答案这种结构阅卷人看着最清晰。当前状态触发事件动作目标状态已创建用户支付扣款、分配订单号已支付已支付商户接单推送消息给骑手已接单已接单骑手到店上报到店时间取餐中取餐中骑手取货更新预计送达时间配送中配送中用户确认送达/骑手点击送达支付结算已完成任意非终态用户取消退款流程已取消任意配送态超时未送达/客诉记录异常、补偿配送异常写出这张表之后一定要补上三个工程要点。第一状态迁移必须幂等同一个“骑手点击送达”事件重复提交不能把订单从“配送中”变成“已取消”所以表里每条迁移都应绑定事件ID做去重。第二加乐观锁版本号防止并发更新覆盖比如用户取消和骑手送达同时发生必须有一个先成功另一个失败重试。第三超时自动降级比如“已支付”后商户超时未接单系统要能自动取消并退款这种问题笔试里不写就少一层亮点。5.2 “附近推荐”接口排序不要一上来就谈模型先谈特征和权重这道题的大意是美团App首页要给用户推荐附近的餐饮商家你会怎么设计排序逻辑。千万别上来就写“用深度学习模型推荐”笔试阅卷人更想看到可解释、可降级、可上线的基础排序框架。我推荐用加权得分排序来组织答案。score w1 × 距离分 w2 × 预计配送时长分 w3 × 商家评分分 w4 × 用户历史偏好分 w5 × 实时补贴力度分然后逐个解释每个特征怎么算。距离分数根据用户坐标和商家坐标做归一化距离越近分越高预计配送时长可以取历史平均配送时间高峰期还要叠加实时拥堵系数商家评分用好评率而非单纯星级避免小样本商家靠几条好评冲到前面用户偏好要用离线算好的物品向量比如用户常点川菜、快餐在线算余弦相似度补贴力度则是运营配置的实时权重。最后一定要写降级策略用户冷启动没有历史行为时把偏好权重调低把距离和评分权重调高定位失败时切换为城市级热门榜单后端超时则直接返回兜底缓存列表。场景题得分的核心不是方案多炫而是“你能把异常情况都想一遍”。6. 四十分钟换三十分笔试时间分配与做题顺序的实操复盘最后聊点真正能在下次笔试里帮你提分的经验。美团的笔试时间通常不算宽裕尤其三道编程题都要求完整代码输出很多人栽在做题顺序上。我的建议是拿到题先花3分钟通读全卷把每道题的难度打个标签先做“读一遍就能想到算法模型”的题再做“需要转换思路”的题。一般编程题第一道是区间合并类或模拟题上手快先做掉能建立信心第二道树的题要处理边界条件放中间稳着来单调栈那道如果5分钟没想透转化关系先跳去做基础选择题回头再战。基础题控制在每题1分钟以内不会的先用排除法标记不要恋战。关于语言笔试环境里C和Java各有优势。C的STL写区间合并、单调栈非常顺手但指针和迭代器容易出错Java写场景题很直观但笔试代码量偏大时有时不够快。我的个人习惯是算法题用C因为map、stack、vector这些容器写起来最快如果公司在线编辑器只有Python也完全可以用Python写DFS和扫描线更短但要注意递归深度限制。备考阶段最好固定一门语言刷题不要临场换枪。还有一个特别容易丢分的地方输入输出没处理好。美团笔试对输出格式要求严格多输出一个空格都算错。用C的话记得关掉cin同步不然大数据量读取会超时。区间合并题的答案记得检查数据范围n边界到10万时int够用但如果时间点数值超过2的31次方必须用long long。我在复盘时把这些坑标出来就是希望你别在“算法对了但格式错了”这种地方白丢分。最后再分享一个我实测有效的小技巧每次笔试结束后趁记忆还热立刻把题目里的业务壳去掉在笔记本上写下它对应的算法模型比如“配送区间最大重叠区间数”“组织架构多叉树最长路径”“空闲骑手矩形最大全1矩阵”。坚持复盘十场之后你会发现美团风格的题目在考场上基本一眼就能看到底——它再怎么换业务描述最内核的算法模型翻来覆去就是那十几个经典问题。把这件事做扎实比盲目刷三百道新题有用得多。