☰
美团2023校招第五场编程题复盘:动态规划与图论实战
2026/10/20 6:48:01 网站建设 项目流程

美团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)。网格大小如果是200x200,K如果不超过网格点数,总状态数是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((V+E)logW),完全能过。

这里有一个很关键的优化点:二分答案的时候,不必每次重新构建邻接表。把所有边按权值排序,然后通过并查集逐步加边,检查起点和终点是否处于同一连通块。这种做法的复杂度是O(ElogE),比二分+BFS的O((V+E)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的核心代码模式,压根没有“处理输入流”的意识,到了赛码上就会措手不及。我在笔试前特意把“读入一个整数二维数组”、“读入带逗号分隔的字符串”、“读入一行经过空格的整数”这几种情况的代码模板整理到文档里,考试时直接复制模板再改逻辑,非常省时间。

经过这几场笔试,一个特别深的体会:笔试考的不仅是算法,更是“在规定时间内,稳定输出高质量代码”的能力。算法思路只是基础,代码的健壮性、对细节的把控,以及快速定位问题的能力,才是真正决定笔试分数的关键。如果你正在准备美团的校招,优先把动态规划和图论这两块吃透,然后把输入输出模板准备好,最后一定记得多刷几套全真模拟题练手。等真正上了考场,你会发现大部分坑你都已经踩过了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询