【备战春招必看】美团2025届春招第1套笔试解析 | 大厂真题通关指南
✅ 春招备战指南 ✅
💡 学习建议:
- 先尝试独立解题(建议用时:90分钟/套)
- 对照解析查漏补缺
- 配套练习题库
互联网必备刷题宝典🔗
📢 美团技术岗笔试重要信息速览
⏰ 笔试时间安排
- 常规场次:每周六交替进行
- 上午场 10:00~11:30
- 晚间场 19:00~20:30
- 通知时间:每周四/五通过邮箱发送考试链接
🧩 笔试题型分布
算法岗 | 选择题 + 5道编程 |
后端开发岗 | 选择题 + 3道编程 |
前端/测试岗 | 选择题 + 2道编程 |
⚙️ 考试设置要点
- 考试平台:牛客网(ACM模式)
- 监考要求:
- 必须开启笔记本前置摄像头
- 禁止使用手机(需小程序锁定)
- 允许使用本地IDE
- 编程规范:
- 严格遵循输入输出格式
- 注意时间复杂度控制(通常1s对应1e8次运算)
📚 笔试经验贴
(所有展示题面均已进行改编处理,保留核心考点)
本题库收录整理自:
- 互联网公开的笔试真题回忆版(经网友投稿)
- 各大技术社区公开讨论的经典题型
- 历年校招考生提供的解题思路
🔍 题库特点:
- 100%真实笔试场景还原
- 包含高频考点题型
- 提供多语言实现参考
- 持续更新2024届最新真题
⚠️ 注意事项:
- 所有题目均来自公开渠道,已进行改编脱敏处理
- 实际笔试可能出现题型变化,请以官方通知为准
🚀 春招备战指南
金三银四求职季即将到来!这里整理了最新美团真题及解析,助你快速掌握笔试套路。建议重点突破以下题型:
- 数组/字符串操作
- 树形结构应用
- 贪心/动态规划
- 区间合并问题
(👇 下附最新笔试真题及详细解析 👇)
真题详解(改编版)
T1
题目内容
小基很喜欢 M 和 T 这两个字母。现在小基拿到了一个仅由大写字母组成的字符串,他可以最多操作 次,每次可以修改任意一个字符。小基想知道,操作结束后最多共有多少个 M 和 T 字符?
输入描述
第一行输入两个正整数 ,代表字符串长度和操作次数。 第二行输入一个长度为
的、仅由大写字母组成的字符串。 其中,
。
输出描述
输出操作结束后最多共有多少个 M 和 T 字符。
样例1
输入:
5 2
MTUAN
输出:
4
说明:修改第三个和第五个字符,形成的为 MTTAM,这样共有 4 个 M 和 T。
题解
这是一道贪心思维题,解题的关键在于理解如何最大化 M 和 T 的数量。
首先统计字符串中非 M 和 T 的字符数量,记为 。这些字符都是可以被修改的候选。
有了操作次数 的限制,实际可修改的字符数量就是
。为什么取最小值?因为即使操作次数很多,能修改的字符数量也不能超过现有的非 M 和 T 字符的数量。
最终答案就是:原有的 M 和 T 的数量加上新增的 M 和 T 的数量,即 。
以样例为例:字符串"MTUAN"中有 3 个非 M 和 T 的字符(U、A、N),操作次数 ,所以最多可以将其中 2 个字符改为 M 或 T,最终得到 4 个 M 和 T。
时间复杂度为 ,只需要遍历一次字符串统计字符数量即可。对于给定的数据范围(
)来说完全足够。
参考代码
C++:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
string s;
cin >> s;
int cnt = 0;
for(char c : s) {
if(c != 'M' && c != 'T') cnt++;
}
cout << n - cnt + min(k, cnt) << endl;
return 0;
}
Python:
n, k = map(int, input().split())
s = input()
cnt = sum(1 for c in s if c not in 'MT')
print(n - cnt + min(k, cnt))
Java:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
String s = sc.next();
int cnt = 0;
for(char c : s.toCharArray()) {
if(c != 'M' && c != 'T') cnt++;
}
System.out.println(n - cnt + Math.min(k, cnt));
}
}
T2
题目内容
小基拿到了一个由正整数组成的数组,但其中有一些元素是未知的(用 0 来表示)。现在小基想知道,如果那些未知的元素在区间 范围内随机取值的话,数组所有元素之和的最小值和最大值分别是多少?共有
次询问。
输入描述
第一行整数 和
,表示数组的长度和询问的次数。 第二行输入
个整数
,其中如果输入的
为 0,那么说明
是未知的。 接下来的
行,每行输入两个正整数
,代表一次询问。
数据范围:
输出描述
输出 行,每行输出两个正整数,代表所有元素之和的最小值和最大值。
样例1
输入:
3 2
3 0 2
1 1
1 2
输出:
6 6
6 7
说明:第二次询问中,最小为 ,最大为
。
题解
这是一道思维题,关键在于理解如何获取最大值和最小值。
对于每个未知数(值为 0 的位置),要使总和最小,显然应该取可选范围的最小值 ;要使总和最大,则应该取可选范围的最大值
。
解题步骤如下:
- 统计数组中值为 0 的元素个数,记为
。
- 统计数组中所有非 0 元素的和,记为
。
- 对于每次询问:
- 最小值 =
- 最大值 =
- 最小值 =
注意:由于数据范围较大(),计算时需要使用 long long 类型避免溢出。
时间复杂度分析:
- 预处理数组需要
- 每次询问只需
的计算
- 总时间复杂度为
对于给定的数据范围(
)完全可以接受。
参考代码
C++:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
int n, q;
cin >> n >> q;
ll sum = 0;
int zero_cnt = 0;
for(int i = 0; i < n; i++) {
int x;
cin >> x;
if(x == 0) zero_cnt++;
else sum += x;
}
while(q--) {
ll l, r;
cin >> l >> r;
cout << sum + zero_cnt * l << " " << sum + zero_cnt * r << endl;
}
return 0;
}
Python:
n, q = map(int, input().split())
a = list(map(int, input().split()))
sum_val = sum(x for x in a if x != 0)
zero_cnt = a.count(0)
for _ in range(q):
l, r = map(int, input().split())
print(sum_val + zero_cnt * l, sum_val + zero_cnt * r)
Java:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int q = sc.nextInt();
long sum = 0;
int zeroCnt = 0;
for(int i = 0; i < n; i++) {
int x = sc.nextInt();
if(x == 0) zeroCnt++;
else sum += x;
}
while(q-- > 0) {
long l = sc.nextLong();
long r = sc.nextLong();
System.out.println((sum + zeroCnt * l) + " " + (sum + zeroCnt * r));
}
}
}
T3
题目内容
小基拿到了一个 的矩阵,其中每个元素是 0 或者 1。小基认为一个矩形区域是完美的,当且仅当该区域内 0 的数量等于 1 的数量。现在,小基希望知道有多少个
的完美矩形区域。需要回答
的所有答案。
输入描述
第一行输入一个正整数 ,代表矩阵大小。 接下来的
行,每行输入一个长度为
的 01 串,用来表示矩阵。 其中,
。
输出描述
输出 行,第
行输出
的完美矩形区域的数量。
样例1
输入:
4
1010
0101
1100
0011
输出:
0
7
0
1
题解
这道题目可以使用二维前缀和来解决。
核心思路:
- 先预处理出二维前缀和数组,用于快速计算任意矩形区域内 1 的个数。
- 枚举所有可能的正方形区域,检查是否完美。
- 一个区域要完美,需要区域内 0 和 1 的数量相等,即 1 的数量应该是区域大小的一半。
具体实现步骤:
- 构建前缀和数组
,表示从
到
的矩形区域内 1 的个数。
- 对于每个边长
,枚举左上角坐标
。
- 计算对应的右下角坐标
。
- 使用前缀和计算该区域内 1 的个数,判断是否等于区域大小的一半。
时间复杂度分析:
- 预处理前缀和需要
- 枚举所有可能的正方形需要
- 总时间复杂度为
在
的数据范围内可以通过。
参考代码
C++:
#include <bits/stdc++.h>
using namespace std;
const int N = 205;
int sum[N][N], n;
char g[N][N];
int get_sum(int x1, int y1, int x2, int y2) {
return sum[x2][y2] - sum[x1-1][y2] - sum[x2][y1-1] + sum[x1-1][y1-1];
}
int main() {
cin >> n;
// 读入矩阵并构建前缀和数组
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
cin >> g[i][j];
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + (g[i][j] == '1');
}
}
// 枚举所有可能的正方形大小
for(int len = 1; len <= n; len++) {
int ans = 0;
// 枚举左上角坐标
for(int i = 1; i + len - 1 <= n; i++) {
for(int j = 1; j + len - 1 <= n; j++) {
int ones = get_sum(i, j, i + len - 1, j + len - 1);
if(ones * 2 == len * len) ans++;
}
}
cout << ans << endl;
}
return 0;
}
Python:
n = int(input())
grid = ['0' * (n+1)] + ['0' + input() for _ in range(n)]
# 构建前缀和数组
sum_matrix = [[0] * (n+1) for _ in range(n+1)]
for i in range(1, n+1):
for j in range(1, n+1):
sum_matrix[i][j] = (sum_matrix[i-1][j] +
sum_matrix[i][j-1] -
sum_matrix[i-1][j-1] +
int(grid[i][j] == '1'))
def get_sum(x1, y1, x2, y2):
return (sum_matrix[x2][y2] -
sum_matrix[x1-1][y2] -
sum_matrix[x2][y1-1] +
sum_matrix[x1-1][y1-1])
# 枚举所有可能的正方形大小
for length in range(1, n+1):
ans = 0
# 枚举左上角坐标
for i in range(1, n-length+2):
for j in range(1, n-length+2):
ones = get_sum(i, j, i+length-1, j+length-1)
if ones * 2 == length * length:
ans += 1
print(ans)
Java:
import java.util.*;
public class Main {
static int N = 205;
static int[][] sum = new int[N][N];
static char[][] g = new char[N][N];
static int n;
static int getSum(int x1, int y1, int x2, int y2) {
return sum[x2][y2] - sum[x1-1][y2] - sum[x2][y1-1] + sum[x1-1][y1-1];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
sc.nextLine(); // 消耗换行符
// 读入矩阵并构建前缀和数组
for(int i = 1; i <= n; i++) {
String line = sc.nextLine();
for(int j = 1; j <= n; j++) {
g[i][j] = line.charAt(j-1);
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] +
(g[i][j] == '1' ? 1 : 0);
}
}
// 枚举所有可能的正方形大小
for(int len = 1; len <= n; len++) {
int ans = 0;
// 枚举左上角坐标
for(int i = 1; i + len - 1 <= n; i++) {
for(int j = 1; j + len - 1 <= n; j++) {
int ones = getSum(i, j, i + len - 1, j + len - 1);
if(ones * 2 == len * len) ans++;
}
}
System.out.println(ans);
}
}
}
T4
题目内容
小基拿到了一个大小为 的数组,他希望删除一个区间后,使得剩余所有元素的乘积末尾至少有
个 0。小基想知道,一共有多少种不同的删除方案?
输入描述
第一行输入两个正整数 。 第二行输入
个正整数
,代表小基拿到的数组。 其中,
,
。
输出描述
输出一个整数,代表删除的方案数。
样例1
输入:
5 2
2 5 3 4 20
输出:
4
题解
这道题目使用双指针算法求解,关键思路如下:
- 统计整个数组中每个数的因子 2 和因子 5 的个数。
- 使用双指针维护删除区间,计算剩余数字中因子的总数。
- 当某个区间删除后不满足条件时,需要缩小删除区间。
- 当某个区间满足条件时,可以计算以当前右端点结尾的所有合法方案。
时间复杂度分析:
- 预处理因子个数:
- 双指针遍历:
总体复杂度:
参考代码
C++:
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
int l = 0, r = 0;
int n, k;
cin >> n >> k;
vector<int> a(n);
vector<array<int, 2>> cnt(n);
// 统计每个数的因子2和5的个数
for(int i = 0; i < n; i++) {
cin >> a[i];
int x = a[i];
while(x % 2 == 0) x >>= 1, l++, cnt[i][0]++;
while(x % 5 == 0) x /= 5, r++, cnt[i][1]++;
}
int res = 0;
array<int, 2> c{l, r}; // 记录当前未被删除的数中因子2和5的总数
int j = 0; // 左指针
// 枚举右指针
for(int i = 0; i < n; i++) {
// 删除当前位置的数
for(int p = 0; p < 2; p++)
c[p] -= cnt[i][p];
// 当不满足条件时,缩小删除区间
while(j <= i && *min_element(c.begin(), c.end()) < k) {
for(int p = 0; p < 2; p++)
c[p] += cnt[j][p];
j++;
}
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力