
美团2023校招技术岗第五场编程题说实话考完之后我缓了挺久。不是因为题量有多大而是有几道题一眼看过去觉得“这个我会”但真正动手写的时候才发现美团出题比我想象中要聪明得多。它不考那种背模板的算法题而是把外卖、地图、商家这些真实业务场景包装进题目里你如果只是会套板子写出来的代码跑样例没问题一到大数据量就露馅。这篇文章不打算写什么“真题答案合集”网上流传的版本很多但大部分只给代码不给思路。我按照第五场的题型风格和考点分布把几个核心类型的题目重新复盘一遍重点讲清楚考场上你是怎么想的、这题想考你什么、暴力解法为什么挂、优化到底优化在哪以及从笔试到面试这些题还能怎么延伸。1. 第五场整体复盘题型分布与考场节奏第五场和其他几场不太一样整体给我的感觉是前两道题是给你热身的第三道开始上强度第四道属于“心态题”——一看就有思路但是越写越觉得细节多最后时间全耗在这。先说题型分布。整场笔试题型分为选择题和编程题两大块。选择题考察范围比较常规Java/C基础、操作系统、网络、数据库偶尔穿插一两道智力题这部分基本靠平时积累临时抱佛脚意义不大。编程题一共4道难度梯度大致是简单模拟、贪心/二分、动态规划、图论变种。这个分布比较符合美团校招笔试的一贯风格难度不是均匀铺开的而是直接把重头戏放在后面两道。考场时间的分配是很多人忽略的问题。我自己的经验是前两道简单题控制在25分钟左右第三道题留40分钟第四道题不要死磕如果15分钟内没有完整的可行思路立刻回头检查前面几道题是否有边界漏判把该拿的分全部拿稳再回来慢慢啃第四道。这里多说一句美团的编程题评测非常严格你以为对的部分用例可能只是通过了公开样例隐藏用例里全是边界条件。我记得第五场有一道题自测样例全过提交后通过率只有20%问题出在数组越界和一个变量该用long却用了int。这种情况在牛客上刷题时不容易暴露但真实笔试里非常常见。另外提一下赛码这个平台。第五场用的就是赛码系统它的输入输出和牛客有点区别尤其是读多行数据时用Scanner逐行读或者BufferedReader批量读的效率差异很大。如果你平时用LeetCode那种核心代码模式习惯了建议提前一两天在赛码网上做几道模拟题练手不然真到笔试环境光是处理输入输出就可能耗掉很多时间。还有一点笔试时浏览器切屏会被监控美团笔试系统会记录切屏次数如果被判断为作弊行为成绩直接作废。所以复习时把知识点放在一个窗口做题时不要来回切。这是很实际的考场纪律问题不要因为这个翻车。2. 题一复盘模拟题的“隐藏要求”比题面更考人第五场第一道编程题从类型上说是经典的模拟题给定一些输入按规则处理输出。规则本身并不复杂属于读题仔细就能做对的范畴但它有一个很典型的陷阱——题目描述里藏着额外条件不好好逐字读题很容易按自己的想法实现结果和预期输出对不上。我把这类题概括为“业务规则模拟”。美团这种互联网公司特别喜欢出这类题因为它跟实际工作场景高度接近给你一份需求文档你需要把文档里的规则翻译成代码。这种能力恰恰是很多校招生欠缺的。大家刷题刷习惯了看到“模拟”两个字就默认是简单的字符串处理和条件判断却忘了读题本身就是考察的一部分。以第五场这道题为例大致场景是外卖平台需要对一批订单做分类处理订单包括订单号、用户ID、商家距离、预计送达时间等字段要求按照特定优先级规则输出。优先级规则里有一个细节是“当距离小于等于3公里时配送费减免”很多人会写成“小于3公里”这一个等于号的差别就会导致大量用例不过。这种细节在笔试里出现真的是在提醒你以后工作中面对需求文档边界条件必须一个个跟产品确认清楚。写这类题的代码时我建议不要一上来就进入“写逻辑”状态先在注释里把规则列成清单。比如规则1按订单号升序输出 规则2距离 3km 减免配送费 规则3优先输出商家距离近的订单 规则4同一距离按预计送达时间排序确认规则之间没有冲突之后再动笔写代码。这样做还有一个好处如果最终输出不对你可以很快定位是哪个规则实现有误而不是在一坨耦合代码里面找bug。实现层面这类题考的是对集合排序和自定义比较器的熟练度。用Java写核心就是Collections.sort配合Comparator或者用Java 8的Comparator.comparing链式写法。但这里有一个性能细节如果一次排序涉及多个字段不要每次都定义一个匿名类直接在Comparator里面写链式比较代码更清晰也不容易写错。另外遇到这种规则复杂的题一定要把测试用例想全。不要说“样例过了就行”样例只是给你一个最低保证。你要自己想几组极致的情况比如所有订单距离都是0、所有订单距离都相同、配送费减免后金额达到0等。笔试评测的隐藏用例很多就是在这种边界上出题。3. 题二复盘贪心策略的证明是拿满分的关键第二道题是典型的贪心题。这类题在美团笔试中出现频率极高因为贪心算法在业务里的应用非常广泛比如骑手派单策略、运力调度、仓库拣货路径规划等本质上都是贪心思想的变体。这道题的场景大致是给定一批配送任务每个任务有开始时间和结束时间骑手一次只能执行一个任务问最多能完成多少个任务。经典的活动选择问题解法也非常标准按照结束时间从小到大排序然后贪心地选第一个不冲突的任务。考场上大部分人能想到这个策略但很多人没有想过为什么按结束时间排序是对的而不是按开始时间排序也不是按时长排序。如果你只停留在“这道题我背过解法”的层面面试官一追问就露馅。我在准备美团面试时专门整理过这类题的证明思路按结束时间排序后每次选择结束时间最早的任务其实是在为后面的任务留出尽可能多的剩余空间。贪心策略正确性的核心依据是“局部最优能推导出全局最优”。这一点在笔试答案里未必需要写出来但面试环节几乎必问。还有一个进阶变体第五场虽然没有直接考但美团很喜欢换壳出如果任务带权重不再是“最多能完成几个”而是“能获得的最大收益”那贪心就不成立了要换成动态规划。所以这块知识点你需要成体系地准备而不是孤立地背一道题。我当时把活动选择、带权活动选择、区间覆盖、区间分组这几类题放在一起复习因为美团笔试题型中区间类问题真的非常多一道题换一个壳本质还是同一套东西。实现层面这类题有一个细节时间区间是否开闭。题目里说的是“结束时间之后才能开始下一个任务”还是“结束时间当天还能接下一个任务”这两种表述对应start end和start end两类判断很多人就是在这里出错。再就是时间单位题目里给的是小时、分钟还是秒直接决定排序和遍历时数据范围如果用了int时间戳换算成秒之后很可能会超范围遇到时间类题目我一般直接上long。4. 题三复盘动态规划的“状态设计”才是分水岭第三道题是整场笔试的分水岭。前面两道题还能靠刷题量撑住这道题开始解题能力一下子就拉开差距了。题目背景大概是这样的给定一个二维网格地图网格的每个位置代表一个商家的配送耗时骑手从左上角出发只能向右或向下移动要求到达右下角并且过程中需要恰好经过K个指定类型的商家求最短总耗时。这题考的是动态规划但核心难点不在于状态转移方程的推导而在于状态的设计。如果你沿用传统“从左上角到右下角最短路径”的DP思路只记录dp[i][j]表示到达(i, j)的最短耗时会发现根本没有办法处理“恰好经过K个指定类型商家”这个约束。因为同一个位置可以由不同的路径到达不同路径对应的已经过商家数量是不同的你需要把“已经过商家数”也纳入状态。我当时的状态设计是这样的dp[i][j][k] 到达(i, j)且已经经过k个指定商家的最短耗时这里k的范围是0到K所以第三维的空间复杂度是O(K)。网格大小如果是200x200K如果不超过网格点数总状态数是200 x 200 x K如果用二维数组存储一维数组按行按列展开空间是可以压下来的。转移方程也比较直接dp[i][j][k] min(dp[i-1][j][k], dp[i][j-1][k]) cost[i][j] 如果 (i, j) 是指定商家 dp[i][j][k] min(dp[i-1][j][k-1], dp[i][j-1][k-1]) cost[i][j]写出来的本质是一个三维DP但这也正是考点所在你能不能想到把约束条件作为DP的一个维度。很多人的瓶颈就在这里因为刷题时习惯了二维DP遇到这种“路径计数”的场景思维没有及时转换过来。考场上这道题最折磨人的地方是边界条件的初始化。起点(0,0)如果是指定商家那么dp[0][0][1]才是合法值dp[0][0][0]在起点不是指定商家时才是合法值。第一行和第一列也需要单独处理因为只能从上方或左方过来。这些边界处理如果一开始没想清楚代码写出来永远离正确答案差一点而且很难查。另外如果K的值非常大比如K大于从起点到终点的最短路径长度直接输出-1即可不需要跑完整DP。这个剪枝非常实用考场上可以极大节省时间。我在做这道题的时候就是因为没有先做这个判断导致跑了很多无用状态虽然不是超时但也白白浪费了时间。很多人可能会问这类题还有没有更优解法如果K比较小可以用状态压缩DP如果网格比较大但K很小可以把K作为状态压缩的二进制位。但笔试场景下标准三维DP已经足够通过全部用例不需要过度优化。当然如果你能把状态压缩的解法写出来肯定是加分项但前提是你对三维DP的边界处理完全有把握。没有把握的时候不要炫技稳扎稳打把常规解法写到满分比写一个半吊子的优化解法要稳得多。5. 题四复盘图论变体题读懂题意比算法本身更难第四道题我拿到手后的第一反应是这是图论题但考的不是最短路径而是一个“是否存在一条路径满足某个约束”的问题。题目场景大概是地图上有若干个配送站点和转运节点有些节点之间禁止通行给定起点和终点问是否存在一条路径且路径长度不超过一个给定上限。第一眼看上去这就是个DFS或BFS能解决的问题但仔细想就会发现数据范围很大节点数和边数都到了10的五次方级别直接DFS一定会超时。标准解法是BFS剪枝或者二分答案BFS验证。这道题真正难的地方在于你需要在考场上识别出它本质上是一个“图可达性路径代价约束”的问题在读题阶段就快速定位到正确的算法方向而不是真的去枚举所有路径。我处理这类题的经验是先不管题目包装成什么业务场景把它抽象成数学结构。比如这道题抽象之后就是“带权无向图给定起点和终点问是否存在一条路径使得路径上的最大边权不超过给定阈值”。一旦抽象到这个层面解法就很清晰了二分答案把边权大于阈值的所有边删掉然后BFS检查连通性。复杂度是O((VE)logW)完全能过。这里有一个很关键的优化点二分答案的时候不必每次重新构建邻接表。把所有边按权值排序然后通过并查集逐步加边检查起点和终点是否处于同一连通块。这种做法的复杂度是O(ElogE)比二分BFS的O((VE)logW)稍微好一点而且实现也更简单——不需要每次二分时清空visited数组最后做题时我选了并查集方案。实现层面有几个容易翻车的点。第一个是图可能不连通起点和终点根本不在一个连通分量里这种要提前判断否则并查集跑完依然返回false白跑一遍。第二个是边的权值范围如果权值很大二分的右边界要设为最大边权而不是1e9这种魔数否则二分次数会变多虽然不超时但浪费几秒钟没必要。第三个是当起点等于终点时路径长度为0答案是true这个特判尤其容易被漏掉。说到这我想额外说一个关于图论题的通用经验美团笔试的第四题往往不是让你裸写一个算法而是要把算法嵌到一个业务场景里。你要是只看题面可能会被一堆业务术语绕晕但一旦抽离出数学模型题目难度就会瞬间下降一个档次。备考阶段我建议大家多练“读题→抽象”这个步骤每天拿几道题故意不看题目标签逼自己在30秒内说出这题考的是什么算法、大致解法是什么。这个能力练好了笔试中的第四题就不再是难关了。6. 笔试中最容易翻车的边界与细节来自真实踩坑经验这一章本来不在计划内但想了想还是单独拿出来写。原因很简单我第五场在线笔试时因为细节问题扣分的情况比思路卡壳更可惜。思路没想到还可以说是能力差距但细节出错就是纯亏。第一个细节是数据类型的选取。C里int的范围大约在正负21亿左右Java的int也是一样。如果题目给出的输入范围是10的9次方级别做加法或乘法后很容易溢出。第五场第三题网格里的耗时累加后轻松超过int上限我一开始用int死活有三四个用例不过改成long立刻全过。这种低级错误考场上非常容易犯因为大脑在专注算法的时候是没空去检查数据范围的。所以我的建议是审题阶段就在草稿纸上把数据范围圈出来凡是涉及累加、累乘的变量默认用long不要省。第二个细节是输出格式。美团笔试的编程题要求输出结果与样例格式完全一致包括空格、换行、大小写。有时候题目要求“YES”和“NO”你写成了“Yes”和“No”评测就是不给过。这种问题在本地IDE上可能不会暴露因为你自己没法验证所以养成习惯输出常量字符串时直接从题目里复制不要自己敲。同样的道理也适用于小数点的精度控制如果题目要求保留两位小数你用printf(%.2f)或String.format(%.2f)都能实现关键在于精确复制格式要求。第三个细节是内存限制。美团笔试系统对于内存的监控比牛客严格尤其是Java默认堆内存限制有时候只有256MB。如果你在DP题里开了一个三维int数组维度是200x200x500这个数组就大约80MB再加上其他数据结构很可能内存超限。所以DP题的状态压缩不是炫技而是实打实的保命手段。第四个细节是输入流的选择。赛码系统的输入数据量经常很大用Scanner逐行读有时候会超时尤其是Java。我建议直接用BufferedReader或StreamTokenizer。很多校招生平时习惯LeetCode的核心代码模式压根没有“处理输入流”的意识到了赛码上就会措手不及。我在笔试前特意把“读入一个整数二维数组”、“读入带逗号分隔的字符串”、“读入一行经过空格的整数”这几种情况的代码模板整理到文档里考试时直接复制模板再改逻辑非常省时间。经过这几场笔试一个特别深的体会笔试考的不仅是算法更是“在规定时间内稳定输出高质量代码”的能力。算法思路只是基础代码的健壮性、对细节的把控以及快速定位问题的能力才是真正决定笔试分数的关键。如果你正在准备美团的校招优先把动态规划和图论这两块吃透然后把输入输出模板准备好最后一定记得多刷几套全真模拟题练手。等真正上了考场你会发现大部分坑你都已经踩过了。