一场美团算法笔试,我写满了编辑器却被判了零分
要说校招笔试哪家最让我记忆深刻,美团绝对排得上前三。倒不是题目有多变态,而是第一次参加大厂在线笔试时,我在自带的本地编辑器里把代码跑得漂漂亮亮,结果提交到牛客网判题系统,直接一个大大的编译错误,当时的崩溃感我现在还记得。
后来复盘才发现,问题出在输入输出处理上——本地能跑是因为我手动输入了测试数据,而在线评测系统需要从标准输入流读取多组数据,格式稍有不对就是零分。这种因为“格式问题”丢掉的分,比不会做题还让人憋屈。
这篇内容我打算根据2023届美团校招算法笔试的备考经历,结合我自己和周围同学的真实踩坑记录,把这类大厂算法笔试的核心题型、做题顺序、代码模板、易错细节全部捋一遍。不管你是正在准备2025届校招,还是刚上大三开始刷题,这篇内容都能帮你少走不少弯路。
先说结论:美团的算法笔试难度在全网大厂里属于中等偏上,不那么“套路”,很喜欢把业务场景(外卖配送、商家排序、用户调度)包装成算法题,核心考点集中在动态规划、贪心、图论、字符串处理、模拟这几大类。题型是选择题加编程题混合,编程题3道左右,满分100分时编程题能占到70分往上。换句话说,编程题是你能不能进面试的分水岭。
1. 一场笔试90分钟,我是怎么分配时间把三题全部写完的
美团校招的在线笔试一般是90分钟,题型分布比较固定:前面是若干道选择题,考察计算机网络、操作系统、数据库的基础知识,后面是2到3道算法编程题。选择题占分不高,但也不是白给的,它背后有一层隐藏逻辑——筛掉那些纯靠背题、没有任何计算机基础功底的人。
先说我的做题顺序。第一轮我会花3分钟把三道编程题全部看一遍,注意是全部,不是做完一道再看下一道。这样做的原因很简单:编程题的难度排序通常不是按题目编号排列的,有时候第1题反而是全卷最难的,后面的题反而简单。如果你死磕第1题,到时间结束时才发现第2、3题很水,那种感觉就是亏大了。
三道题快速看完之后,我会预估一个难度梯度,比如“第1题中等、第2题简单、第3题困难”。然后先把第2题这种简单题秒掉,锁定基本分,再回头啃第1题或第3题。如果一道题10分钟没有任何思路,先跳过,千万不要硬刚,等最后有剩余时间再回头兜底。
这里有一个特别实用的细节:很多题存在部分分机制。也就是说,即使你的算法不是最优解,甚至只能过一部分测试用例,判题系统也会按通过的比例给分。比如最后一道DP(动态规划)题你写了个暴力递归,时间复杂度很高,但数据量小的测试点能过,你就能拿到百分之二三十的分数。所以哪怕不会最优解,也一定要写点东西上去,空提交等于直接送掉整题的分。
2. 题型结构拆解:美团笔试真正在考什么
美团算法笔试的题目包装风格,一句话形容是“业务即题目”。对比字节跳动喜欢直接出纯粹的算法题,美团更喜欢在题目背景里套一层业务场景。比如外卖骑手的配送路线优化、商家的排序策略、用户红包的补贴分配,这些场景包装背后藏着的其实是经典的算法模型。你如果擅长从题干里抽离出数学本质,这道题就已经解了一半。
2.1 选择题:靠押题不如靠扎实基础
选择题大概占20到30分,考的内容比较杂,高频知识点包括:
- TCP三次握手和四次挥手的状态迁移
- 操作系统的进程调度算法(先来先服务、短作业优先、时间片轮转)
- 数据库事务的隔离级别(脏读、不可重复读、幻读)
- 二叉树的遍历序列还原(已知前序中序求后序这种)
- 哈希冲突的解决方法(链地址法、开放定址法)
- 面向对象的三大特性与多态的实现原理
这部分我建议大家不要花太多精力去搞什么考前突击,因为范围太广了。最好的准备方式是刷牛客上的计算机基础题,以及把《计算机网络:自顶向下方法》和操作系统教材的课后题过一遍。选择题的目标不是拿满分,而是控制在错3题以内。
2.2 编程题:三道题的难度矩阵
以我的经验来看,美团的编程题会尽量避开那种烂大街的模板题,很少直接考“最长公共子序列”“背包九讲”这类原题。他们喜欢做的动作是:把一个经典算法模型藏进一个故事里。
比如外观描述像是“小美要安排外卖骑手在不同商家取餐并送往用户”,抽离出来可能就是一个带权重的最短路径问题;再比如外观描述是“某商圈有多个商家,需要对优惠券分配进行优化”,实际上考的是贪心加排序。
这种包装方式对两类人特别不友好:一类是只背模板、不理解算法本质的人,换个情境就认不出题了;另一类是审题不仔细、被题干故事带跑偏的人,会陷入思考业务逻辑,而忘记用经典算法去求解。我见过太多人把时间浪费在揣摩“美团的外卖业务到底怎么运作”上,其实完全没必要。
正确做法是:读题时直接在草稿纸上抽象,把题干里的名词替换掉。不要想“骑手怎么走最优”,要想“这张图求最短路径”;不要想“商家怎么排序更合理”,要想“这个排序的关键比较函数是什么”。抽离完成之后,这道题就变成了你可以直接套模板的常规题。
3. 四个高频考点的现场破解实例
为了讲得更具体,我从2023届美团校招笔试的题型方向出发,结合牛客网、小红书、知乎上的大量面经复盘,把最常出现的四类考点逐一拆解。题目本身我做了脱敏重构,保证不涉及真实原题,但题型结构和解题思路是高度一致的。
3.1 动态规划:外卖配送路径的状态设计
美团笔试里动态规划几乎是必考的,但很少考那种一眼就看出是DP的题,更多是“状态转移方程需要你自己设计”的类型。我印象最深的是2023届出现过一道和配送路径相关的题目:有若干用户分布在一条直线上,外卖员需要从起点出发,以某种顺序依次服务用户,要求最小化总路程。
这类题的第一反应可能是贪心,但仔细一想就会发现贪心不对——因为路径可以双向选择,每次选最近的用户并不能保证全局最优。正确建模是区间DP:把已服务的用户看成一个连续区间,用dp[i][j][0/1]表示“已经服务完区间[i, j]内的用户,外卖员当前在左端点还是在右端点”时的最小路程。
// C++ 状态定义示例 // dp[i][j][0]:已服务 [i, j] 区间,位于 i // dp[i][j][1]:已服务 [i, j] 区间,位于 j vector<vector<vector<long long>>> dp(n, vector<vector<long long>>(n, vector<long long>(2, INF))); dp[i][i][0] = dp[i][i][1] = abs(users[i] - startPos); // 从起点直冲第一个用户 // 转移时,从扩展一个用户的来源位置累加路程差这个状态设计的核心逻辑是:外卖员走过的用户必然是连续的,因为服务过的用户没有必要再回去,所以区间模型天然成立。现场推导状态方程时我建议用表格法,把小区间推到大区间,心里会更踏实。
DP历来是算法笔试的分水岭,40%的人死在第2题和第3题上。如果你现在时间还充裕,务必把线性DP、背包、区间DP、状压DP这几个方向好好过一遍,状态设计、转移方程、初始化和优化技巧一个都不能漏。
3.2 贪心加排序:商家配送的区间覆盖问题
2023届笔试里有一道让我印象深刻的题,外观场景是某地区有若干商家,每家有一个配送范围区间,问至少需要多少位骑手才能覆盖所有商家的配送需求。剥掉外衣之后,这就是一道经典的区间调度类贪心题。
区间覆盖最少骑手数这个问题,细想之下其实有两种变体。第一种是“选最少区间覆盖整个目标区间”,第二种是“所有区间需要的最大重叠深度”。美团的题更常考后者:将所有区间按左端点排序,用小根堆维护当前已分配的骑手的最早空闲时间,逐个区间判断是复用已有骑手还是新开骑手。
// C++ 贪心示例框架 sort(intervals.begin(), intervals.end()); // 按左端点升序 priority_queue<int, vector<int>, greater<int>> pq; // 记录每名骑手的结束时间 for (auto [l, r] : intervals) { if (!pq.empty() && pq.top() <= l) { pq.pop(); // 最早空闲的骑手可以复用 } pq.push(r); // 这名骑手的新结束时间 } int ans = pq.size(); // 需要的骑手数贪心题最难的点不是代码,而是证明贪心策略的正确性。现场答题时不需要写严格数学证明,但你必须在心里确认“为什么按左端点排序,顺序处理就是最优的”。我的验证套路是疯狂举反例:如果先处理区间短的会怎样?如果按右端点排序会怎样?举两三个反例发现推不翻,就果断相信这个策略。
3.3 图论变种:商家地图上的连通性与最短路
图论题目在美团笔试里出现频率也不低,尤其是最小生成树和单源最短路径这两个方向。因为外卖配送场景天然和地图、路径绑定,所以图论很容易被包装成业务题。有一道我印象深刻的题是这样的:给定一个配送区域的地图,若干商家节点和道路,求从外卖站点出发送完所有商家再返回的最短路径长度。
乍一看是旅行商问题(TSP),但数据范围较小,可以用状态压缩DP来求解:dp[mask][i]表示已经送过集合mask里的商家,当前在节点i的最短时间。先用Floyd算法预处理所有节点之间的最短距离,再用状压DP枚举子集转移。
// Python 状压DP思路示例 # dist[i][j] 由 Floyd 预处理得出 # dp[mask][i]:送过 mask 集合的商家,当前位置为 i 的最短时长 dp = [[inf] * n for _ in range(1 << m)] for i in range(m): dp[1 << i][i] = dist[start][i] for mask in range(1 << m): for i in range(m): if not (mask >> i) & 1: continue for j in range(m): if (mask >> j) & 1: continue nmask = mask | (1 << j) dp[nmask][j] = min(dp[nmask][j], dp[mask][i] + dist[i][j])这种题对熟练度的要求很高,如果现场才去推Floyd和状压DP的转移公式,大概率时间不够。所以我建议备好一套自己的图论模板库:Floyd、Dijkstra、SPFA、Kruskal、并查集,全部提前封装好。别嫌这步骤繁琐,考场上一分钟能定生死。
3.4 字符串与模拟:批量订单解析里的分而治之
不要小看了字符串处理和模拟类题目,美团的笔试非常喜欢用这类题来卡那些算法很强但代码实现能力弱的同学。有一年出现过一道订单解析题:输入是一串带嵌套结构的数据,要求解析出每一个订单的关键字段,字段之间有多层括号嵌套,还要处理转义字符。
这类题没有太多算法含量,但非常考验对边界的处理能力。我的建议是:无论多简单的模拟题,都先拆成小的功能函数再写。例如括号解析单独封装一个函数,字符串切分单独封装一个函数,字段预处理单独封装一个函数。这样如果某个函数出错,你可以单独测试它,而不是在一个超长的main函数里大海捞针。
容易翻车的地方包括:字符串结尾的空字符处理、多个连续分隔符造成的空字符串、转义符影响了分隔符判断、整型溢出。2023届那个订单解析题,我知道有挺多人挂在“订单内容里本身有括号”这个反直觉的坑上——审题时注意看转义规则,千万不要想当然。
4. ACM模式与输入输出的生死线:本地跑通不等于提交通过
开篇提到的编译错误,其实是很多第一次参加线上笔试的人都会踩的坑。大厂在线笔试普遍采用ACM模式,也就是你写的代码需要自己处理标准输入和输出,而不是像LeetCode那样只需要补全函数体。
这两种模式到底有什么本质区别?讲个通俗的比喻:LeetCode模式是你在食堂打饭,告诉阿姨要什么菜,阿姨帮你配好放盘子里;ACM模式是给你一堆食材,你要自己洗、切、炒、装盘。在LeetCode上你只需要实现一个类方法,参数和返回值框架都给好了;ACM模式下你需要自己读取数据、自己解析格式、自己输出结果,格式稍微不对,判题系统就会判定答案错误。
美团校招笔试几乎全是ACM模式。这意味着你至少需要熟练掌握以下几类输入输出模板:
- 读取一个整数、两个整数、N个整数(读入后存入数组)
- 读取一个字符串(含空格和不含空格两种情况)
- 读取多组测试用例,以文件结束符EOF终止
- 读取矩阵数据(二维数组)
这里我直接给一套C++常用的输入输出模板,强烈建议提前保存在本地编辑器里。
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } // 处理逻辑... cout << ans << "\n"; // 建议 \n 而不是 endl,避免不必要的缓冲刷新 return 0; }多组输入的情况下,代码逻辑要包在while循环里:
int T; cin >> T; while (T--) { // 每组独立的处理逻辑 }还有一个细节,如果题目没说输入有多组测试用例,就用单组处理;如果说了“输入包含多组测试用例,以EOF结束”,那就要用while循环配合cin的判断。很多人在这个点上判断错误,结果导致超时或者死循环。
Python的话,我建议记住下面这个万能输入模板:
import sys def solve(): data = sys.stdin.read().split() # 按顺序取出每个数字,用迭代器方式避免搞乱索引 it = iter(data) t = int(next(it)) for _ in range(t): n = int(next(it)) arr = [int(next(it)) for _ in range(n)] # 处理逻辑 if __name__ == "__main__": solve()把全部内容一次性读进来再切分,比逐行用input()读要快得多,在数据量大时能避免Python输入耗时过高导致超时的问题。
5. 现场提交最容易翻车的五个细节
结合自己和身边同学的真实经历,我整理了五个在线笔试最容易翻车、但完全可以在考前规避的细节。每一条都是真实血的教训。
5.1 注意返回类型,long long不是可选项
如果题目的数据范围是10^5,那么很多中间结果和最终答案很容易爆int。比如求和题,10^5个数,每个数10^5,总和就是10^10,超过int的21亿上限,必须用long long。
我的习惯是:只要看见数据范围大于10^5,或者题目涉及累加、乘积、路径长度计算,直接无脑用long long,绝不犹豫。不要高估int的能力,也不要觉得“数据应该不会那么极端”。笔试判题系统里什么边界数据都有,忘了long long就是一长串Wrong Answer。
5.2 数组越界与边界值检查
二分查找、双指针、滑动窗口这类题,特别容易出现数组越界。测试用例规模小的时候能过,一旦上了边界数据就崩。我建议在写完核心逻辑后,花至少一分钟专门过一遍边界情况:数组为空、数组长度为1、所有值相同、目标值在最左端/最右端、目标值不存在。
这一步很枯燥,但它能救你大量分数。我认识一位同学,在一次模考中因为没处理“数组长度为1”的情况,一道30分的题直接0分,前功尽弃。
5.3 编译器版本差异与万能头文件的坑
在线笔试系统通常支持C++14或C++17,也支持#include <bits/stdc++.h>这个万能头文件,但不是所有平台都支持。有些平台编译会报错,这时可以改成逐个引入你需要的头文件:#include <iostream>、#include <vector>、#include <algorithm>这些。
另外auto、unordered_map、priority_queue在新版本里都能用,但如果你用了一些C++17的新特性,最好先确认平台的编译器版本。在线笔试不像本地,可以随便用标准,真的提交不过就只能干瞪眼。
5.4 递归爆栈问题
有些题目用深度优先搜索递归实现很直观,但如果数据规模较大(比如n等于10^5),递归深度过高,可能会在运行时报栈溢出错误。这时要么手动改成显式栈的迭代写法,要么用Java/Python的同学要注意设置递归深度限制。
# Python 中增加递归深度限制 import sys sys.setrecursionlimit(10**7)但即使设置了递归限制,Python在大规模数据下仍然可能超时,所以如果是深层递归的场景,我最推荐的做法还是用栈模拟来替代递归。判断递归深度是否稳定的办法很简单:如果递归深度和输入规模成正比,且规模很大,就要警惕。
5.5 输出格式强迫症
最后这个是我最想强调的坑:输出格式。
- 题目要求输出“YES”或“NO”,你输出了“Yes”或“yes”,错误。
- 题目要求每个数字中间用空格隔开,你多打了行尾空格,有些判题系统会判错。
- 题目要求保留两位小数,你丢掉了
fixed和setprecision(2),错误。 - 题目要求“每个样例输出后跟一个换行”,你漏了换行,错误。
这些格式问题在做题时往往因为“逻辑对了”而被忽略,但判题系统是铁面无私的。最好的办法是在本地测试的时候严格按照题目描述的输出格式确认一遍,甚至可以把样例输出复制过来直接对比字符数量。
6. 从笔试结束到拿到面试:复盘方法和后续规划
笔试交卷只是第一关,70分以下简历大概率沉底,80分以上才有竞争力,这是大家心照不宣的分数线。所以笔试结束后的72小时,是复盘黄金期。不要急着对答案就完事,一定要把每道题从头到尾重新写一遍最优解,整理到自己的错题本里,这样下次同类题就不会再慌。
6.1 如何做一次高质量复盘
复盘的第一步是回忆并记录自己当时的三道编程题分别用了什么思路、卡在了哪里、耗时多久。第二步是查看牛客网或讨论帖里别人的解法,注意对比时间复杂度和空间复杂度。第三步是思考是否可以优化:暴力解法能不能用二分优化?二维DP能不能滚动数组降维?图论题能不能用更短的最短路算法?
这里我建议你建立一份个人错题集,按“题型—考点—错误类型—标准解法”四个字段整理。比如“动态规划—区间DP—状态设计错误—区间端点维度加左右位置状态”。时间久了,这份错题集就是你笔试备考最宝贵的资料。
6.2 笔试后的24小时到48小时,你该做些什么
笔试结束后,很多同学急着刷下一套题,但我会建议先做另一件事:把美团历年的笔试真题以及牛客网上题单按考点分类,找到自己最薄弱的一类,做5道同类型题巩固。
原因是笔试题目常有“换皮”的情况,核心算法模型基本稳定。如果这次在区间DP上栽了跟头,下次大概率还会出现类似考点的题。与其广撒网,不如先精准补漏。
6.3 面试衔接:笔试中暴露出的算法弱项会被面试追问
很多人以为笔试交卷后就能高枕无忧,其实面试官是可以看到你笔试成绩的,甚至会针对性地追问笔试题目。我当时就被问过:“你说说这道题如果数据量再大十倍,你打算怎么优化?”如果你只是过了一遍最优解却没想过扩展场景,现场很容易卡壳。
所以我的建议是:笔试里的每道题,至少要准备一版优化的思路。比如暴力枚举的题想想怎么剪枝,O(n^2)的DP想想能不能斜率优化或者用数据结构加速,BFS想想能不能双向BFS或A*搜索。不要觉得这是在浪费时间,面试场上你多答出这一层,通过率能翻一倍不止。
7. 备考美团笔试,我的最终建议清单
最后给一份我基于实战总结的备考清单,希望对正在准备美团算法笔试的同学有实际参考价值。
第一,如果距离笔试还有一个月以上,以系统刷题为主,优先吃透动态规划、贪心、图论、字符串模拟、数据结构(栈、队列、哈希、堆)这几大模块。第二,如果只剩两周,以真题和模拟题为主,每天至少保证做三道完整编程题,且一定要在ACM模式下写、在在线评测系统里交。第三,如果只剩三天,以复习模板和错题集为主,不要再开新题,把DP、最短路、最小生成树、并查集、二分答案、滑动窗口这几类通用模板在本地编辑器里打一遍,确保随时都能调出来。
我想特别强调一个很多人忽视的备考神器:牛客网的“笔试练习”模块。你可以选公司和年份,模拟真实笔试环境,在线计时、在线提交、查看排名。一定要把自己放在真实的紧张感里来练习,这不仅练技术,也练心理。我第一次模拟的时候连输入输出都写错了,但练了三次之后,状态就能稳定下来。
最后再说一个心态问题:美团笔试的题量不算少,心态一崩,后面全盘皆输。我见过很多基础不错的同学,因为前两道选择题卡住影响了情绪,导致后面编程题完全没有状态。我的建议是遇到卡壳的题,先在草稿纸上写下“这题的考点是什么,我现在该用什么策略”,而不是一直盯着屏幕发呆。一旦从“怎么这么久还没做出来”切换成“这题考的是图论,我用Dijkstra试试”,大脑就会自然回到正轨。
从准备笔试到最终拿到面试机会,整个过程其实是一场技术和心态的双重修行。算法基础决定了你的下限,而考场上的时间分配、输入输出处理、状态切换决定了你的上限。希望这份基于真实踩坑经验的总结能让你少走一些弯路,愿大家都能稳稳拿下笔试,顺利走到面试环节。