✅ 春招备战指南 ✅
💡 学习建议:
- 先尝试独立解题(建议用时:90分钟/套)
- 对照解析查漏补缺
- 配套练习题库
互联网必备刷题宝典🔗
📢 美团技术岗笔试重要信息速览
⏰ 笔试时间安排
- 常规场次:每周六交替进行
- 上午场 10:00~11:30
- 晚间场 19:00~20:30
- 通知时间:每周四/五通过邮箱发送考试链接
🧩 笔试题型分布
岗位类型 | 题目构成 |
---|---|
算法岗 | 选择题 + 5道编程 |
后端开发岗 | 选择题 + 3道编程 |
前端/测试岗 | 选择题 + 2道编程 |
⚙️ 考试设置要点
- 考试平台:牛客网(ACM模式)
- 监考要求:
- 必须开启笔记本前置摄像头
- 禁止使用手机(需小程序锁定)
- 允许使用本地IDE
- 编程规范:
- 严格遵循输入输出格式
- 注意时间复杂度控制(通常1s对应1e8次运算)
📚 笔试经验贴
(所有展示题面均已进行改编处理,保留核心考点)
本题库收录整理自:
- 互联网公开的笔试真题回忆版(经网友投稿)
- 各大技术社区公开讨论的经典题型
- 历年校招考生提供的解题思路
🔍 题库特点:
- 100%真实笔试场景还原
- 包含高频考点题型
- 提供多语言实现参考
- 持续更新2024届最新真题
⚠️ 注意事项:
- 所有题目均来自公开渠道,已进行改编脱敏处理
- 实际笔试可能出现题型变化,请以官方通知为准
🚀 春招备战指南
金三银四求职季即将到来!这里整理了最新美团真题及解析,助你快速掌握笔试套路。建议重点突破以下题型:
- 数组/字符串操作
- 树形结构应用
- 贪心/动态规划
- 区间合并问题
(👇 下附最新笔试真题及详细解析 👇)
真题详解(改编版)
T1:四级考试分数计算
题目内容
众所周知,“全国大学生英语四级考试”(以下简称 CET4)的满分为 710 分。在经过三次的 CET4 考试后,小基终于如愿通过了四级。已知 CET4 的总分数由三大项构成,分别是:听力、阅读、写作。现在已知小基的总分 k k k,且他的"写作"得分比"听力"高了 x x x 分,比"阅读"得分低了 y y y 分,你能求出他的三个大项分别得了多少分吗?
输入描述
输入包含一行三个整数,分别表示题中所述的 k ( 1 ≤ k ≤ 710 ) k(1\le k\le 710) k(1≤k≤710), x , y ( − 120 ≤ x , y ≤ 120 ) x,y(-120\le x,y\le 120) x,y(−120≤x,y≤120)(保证输入合法,即保证算出的答案一定是正整数)。
输出描述
输出包含三个非负整数 a , b , c a,b,c a,b,c,分别表示小基"听力"、“阅读”、"写作"三大项分别的得分。
样例1
输入:
441 1 -20
输出:
153 134 154
题解
这是一道简单的数学题。设写作得分为 a a a,则有 a + ( a − x ) + ( a − y ) = k a+(a-x)+(a-y)=k a+(a−x)+(a−y)=k,从而推导出 a = k − y + x 3 a=\frac{k-y+x}{3} a=3k−y+x。进而可以计算出其他两项。
时间复杂度: O ( 1 ) O(1) O(1)。
三语言参考代码
- Python
total, diff1, diff2 = map(int, input().split())
writing = (total - diff2 + diff1) // 3
print(writing - diff1, writing + diff2, writing)
- Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int total = sc.nextInt();
int diff1 = sc.nextInt();
int diff2 = sc.nextInt();
int writing = (total - diff2 + diff1) / 3;
System.out.println((writing - diff1) + " " + (writing + diff2) + " " + writing);
}
}
- C++
#include <iostream>
using namespace std;
int main() {
int total, diff1, diff2;
cin >> total >> diff1 >> diff2;
int writing = (total - diff2 + diff1) / 3;
cout << (writing - diff1) << " " << (writing + diff2) << " " << writing;
return 0;
}
T2:数组最大值计算
题目内容
小基拿到了一个数组。他定义 f ( i ) f(i) f(i) 为:将第 i i i 个元素翻倍后,数组的最大值。现在小基希望你求出 f ( 1 ) f(1) f(1) 到 f ( n ) f(n) f(n) 的值。
输入描述
第一行输入一个正整数
n
n
n,代表数组大小。
第二行输入
n
n
n 个正整数
a
i
a_i
ai,代表数组。
1
≤
n
≤
2
×
1
0
5
1\le n\le 2\times 10^5
1≤n≤2×105
1
≤
a
i
≤
1
0
9
1\le a_i\le 10^9
1≤ai≤109
输出描述
n n n 个正整数,用空格隔开,代表 f ( 1 ) f(1) f(1) 到 f ( n ) f(n) f(n) 的值。
样例1
输入:
5
1 3 2 5 4
输出:
5 6 5 10 8
题解
对于位置 i i i 而言, f ( i ) f(i) f(i) 由以下三个部分组成:
- 左边的最大值
left_max
- 右边的最大值
right_max
- 2 a [ i ] 2a[i] 2a[i]
可以预处理出后缀数组 r [ i ] r[i] r[i] 表示位置 i i i 右边的最大值,左边的最大值可以一边遍历一边处理。
时间复杂度: O ( n ) O(n) O(n)。
三语言参考代码
- Python
n = int(input())
nums = list(map(int, input().split()))
suffix_max = [0] * (n + 1)
for i in range(n-1, 0, -1):
suffix_max[i] = max(suffix_max[i+1], nums[i])
prefix_max = 0
for i in range(n):
print(max(prefix_max, nums[i]*2, suffix_max[i+1]), end=' ')
prefix_max = max(prefix_max, nums[i])
- Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n];
for(int i = 0; i < n; i++) nums[i] = sc.nextInt();
int[] suffixMax = new int[n+1];
for(int i = n-1; i > 0; i--) {
suffixMax[i] = Math.max(suffixMax[i+1], nums[i]);
}
int prefixMax = 0;
for(int i = 0; i < n; i++) {
System.out.print(Math.max(Math.max(prefixMax, nums[i]*2), suffixMax[i+1]) + " ");
prefixMax = Math.max(prefixMax, nums[i]);
}
}
}
- C++
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> nums(n);
for(int i = 0; i < n; i++) cin >> nums[i];
vector<int> suffixMax(n+1);
for(int i = n-1; i > 0; i--) {
suffixMax[i] = max(suffixMax[i+1], nums[i]);
}
int prefixMax = 0;
for(int i = 0; i < n; i++) {
cout << max(max(prefixMax, nums[i]*2), suffixMax[i+1]) << " ";
prefixMax = max(prefixMax, nums[i]);
}
return 0;
}
T3:字符串修改
题目内容
小基有两个长度相等的字符串,第一个字符串为 s,第二个字符串为 t。小基每次可以选择一个字符串的一个前缀,然后选择一个字母 c,将选择的前缀的所有字母都变成 c。小基想知道他最少要操作几次可以使得 s 和 t 相等。
输入描述
第一行输入一个长度不超过
1
0
5
10^5
105 的字符串
s
s
s。
第二行输入一个长度与
s
s
s 相等的字符串
t
t
t。
输出描述
第一行输出一个整数
m
m
m 表示答案。
接下来 m 行,每行输出用空格隔开的
i
,
j
,
c
i,j,c
i,j,c 表示选择第
i
i
i 个字符串的长度为
j
j
j 的前缀,将前缀所有字母变成 c。
样例1
输入:
aabc
abcc
输出:
2
2 3 b
2 2 a
题解
思维题。首先找到最长的相同后缀,假设后缀的起始位置为 i,如果 s 或 t 的前 i-1 的前缀都等于一个字符 c,那么让另外一个字符串变成这个 c 即可。
时间复杂度: O ( n ) O(n) O(n)。
三语言参考代码
- Python
s = input()
t = input()
n = len(s)
i = n - 1
while i >= 0 and s[i] == t[i]:
i -= 1
if i < 0:
print(0)
else:
aok = bok = 1
for j in range(1, i + 1):
if s[0] != s[j]: aok = 0
if t[0] != t[j]: bok = 0
if aok:
print("1")
print(f"2 {i + 1} {s[0]}")
elif bok:
print("1")
print(f"1 {i + 1} {t[0]}")
else:
print("2")
print(f"1 {n} a")
print(f"2 {n} a")
- Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.next();
String t = sc.next();
int n = s.length();
int i = n - 1;
while (i >= 0 && s.charAt(i) == t.charAt(i)) i--;
if (i < 0) {
System.out.println(0);
return;
}
boolean aok = true, bok = true;
for (int j = 1; j <= i; j++) {
if (s.charAt(0) != s.charAt(j)) aok = false;
if (t.charAt(0) != t.charAt(j)) bok = false;
}
if (aok) {
System.out.println(1);
System.out.println("2 " + (i + 1) + " " + s.charAt(0));
} else if (bok) {
System.out.println(1);
System.out.println("1 " + (i + 1) + " " + t.charAt(0));
} else {
System.out.println(2);
System.out.println("1 " + n + " a");
System.out.println("2 " + n + " a");
}
}
}
- C++
#include <iostream>
#include <string>
using namespace std;
int main() {
string s, t;
cin >> s >> t;
int n = s.length();
int i = n - 1;
while (i >= 0 && s[i] == t[i]) i--;
if (i < 0) {
cout << 0 << endl;
return 0;
}
bool aok = true, bok = true;
for (int j = 1; j <= i; j++) {
if (s[0] != s[j]) aok = false;
if (t[0] != t[j]) bok = false;
}
if (aok) {
cout << "1\n2 " << i + 1 << " " << s[0] << endl;
} else if (bok) {
cout << "1\n1 " << i + 1 << " " << t[0] << endl;
} else {
cout << "2\n1 " << n << " a\n2 " << n << " a" << endl;
}
return 0;
}
T4:平衡子序列计数
题目内容
小基定义一个字符串是平衡串,当且仅当该字符串仅包含两种字符,且两种字符出现的次数相等。例如"ababba"是平衡串。现在小基拿到了一个仅由小写字母组成的字符串,他想知道该字符串有多少子序列是平衡串?
输入描述
第一行输入一个正整数
n
n
n,代表字符串长度。
第二行输入一个长度为
n
n
n 的、仅由小写字母组成的字符串。
1
≤
n
≤
200000
1\leq n \leq 200000
1≤n≤200000
输出描述
输出一个整数表示答案,由于答案可能很大,请输出答案对 1 0 9 + 7 10^9 +7 109+7 取模的结果。
样例1
输入:
5
ababc
输出:
9
题解
统计每个字符出现次数,对于每对字符,计算它们能组成的平衡子序列数量。对于出现 x 次和 y 次的两个字符,可以组成长度为 2,4,6,…,2*min(x,y) 的平衡子序列。
时间复杂度: O ( 2 6 2 × n ) O(26^2 \times n) O(262×n)。
三语言参考代码
- Python
MOD = 10**9 + 7
n = int(input())
s = input()
cnt = [0] * 26
for c in s:
cnt[ord(c) - ord('a')] += 1
ans = 0
for i in range(26):
for j in range(i+1, 26):
v = min(cnt[i], cnt[j])
for k in range(1, v+1):
ans = (ans + comb(cnt[i], k) * comb(cnt[j], k)) % MOD
print(ans)
- Java
import java.util.*;
public class Main {
static final int MOD = 1000000007;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String s = sc.next();
int[] cnt = new int[26];
for (char c : s.toCharArray()) {
cnt[c - 'a']++;
}
long ans = 0;
for (int i = 0; i < 26; i++) {
for (int j = i + 1; j < 26; j++) {
int v = Math.min(cnt[i], cnt[j]);
for (int k = 1; k <= v; k++) {
ans = (ans + combination(cnt[i], k) * combination(cnt[j], k) % MOD) % MOD;
}
}
}
System.out.println(ans);
}
}
- C++
#include <iostream>
#include <vector>
using namespace std;
const int MOD = 1e9 + 7;
int main() {
int n;
string s;
cin >> n >> s;
vector<int> cnt(26);
for (char c : s) cnt[c - 'a']++;
long long ans = 0;
for (int i = 0; i < 26; i++) {
for (int j = i + 1; j < 26; j++) {
int v = min(cnt[i], cnt[j]);
for (int k = 1; k <= v; k++) {
ans = (ans + 1LL * combination(cnt[i], k) * combination(cnt[j], k)) % MOD;
}
}
}
cout << ans << endl;
return 0;
}
T5:请客方案计数
题目内容
小基有 n n n 个朋友,他准备请其中一些朋友来吃饭。其中有一些朋友有暗恋关系:假设 a 暗恋 b,那么小基带上 b 的时候 a 也必须去,否则 a 就会不开心。小基想知道,一共有多少种不同的请客方案可以让每个人都开心?
输入描述
第一行输入两个正整数
n
,
m
n,m
n,m,代表朋友数量、暗恋的关系数量。
接下来的 m 行,每行输入两个正整数
u
,
v
u,v
u,v,代表第
u
u
u 个人暗恋第
v
v
v 个人。
1
≤
n
,
m
≤
1
0
5
1\leq n,m \leq 10^5
1≤n,m≤105
1
≤
u
,
v
≤
n
1\leq u,v \leq n
1≤u,v≤n
保证每个人最多只会暗恋一个人。
样例1
输入:
2 1
1 2
输出:
2
题解
使用强连通分量算法处理环状暗恋关系,然后对每个连通分量进行动态规划。对于每个人,如果他来了,他暗恋的人也必须来;如果他不来,他暗恋的人可来可不来。
时间复杂度: O ( n + m ) O(n+m) O(n+m)。
三语言参考代码
- Python
def tarjan(u):
global timestamp, scc_cnt
timestamp += 1
low[u] = dfn[u] = timestamp
stk.append(u)
in_stk[u] = True
for v in g[u]:
if dfn[v] == 0:
tarjan(v)
low[u] = min(low[u], low[v])
elif in_stk[v]:
low[u] = min(low[u], dfn[v])
if low[u] == dfn[u]:
while True:
y = stk.pop()
id[y] = scc_cnt
in_stk[y] = False
if y == u:
break
scc_cnt += 1
n, m = map(int, input().split())
g = [[] for _ in range(n)]
for _ in range(m):
u, v = map(int, input().split())
u -= 1; v -= 1
g[v].append(u)
low = [0] * n
dfn = [0] * n
stk = []
in_stk = [False] * n
id = [0] * n
timestamp = scc_cnt = 0
for i in range(n):
if dfn[i] == 0:
tarjan(i)
print((pow(2, scc_cnt, MOD) - 1) % MOD)
- Java
import java.util.*;
public class Main {
static final int MOD = 1000000007;
static int n, m;
static List<Integer>[] g;
static int[] low, dfn, stk, id;
static boolean[] inStk;
static int timestamp = 0, sccCnt = 0, top = -1;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
g = new List[n];
for (int i = 0; i < n; i++) g[i] = new ArrayList<>();
for (int i = 0; i < m; i++) {
int u = sc.nextInt() - 1;
int v = sc.nextInt() - 1;
g[v].add(u);
}
low = new int[n];
dfn = new int[n];
stk = new int[n];
inStk = new boolean[n];
id = new int[n];
for (int i = 0; i < n; i++)
if (dfn[i] == 0) tarjan(i);
System.out.println((pow(2, sccCnt, MOD) - 1 + MOD) % MOD);
}
static void tarjan(int u) {
low[u] = dfn[u] = ++timestamp;
stk[++top] = u;
inStk[u] = true;
for (int v : g[u]) {
if (dfn[v] == 0) {
tarjan(v);
low[u] = Math.min(low[u], low[v]);
} else if (inStk[v]) {
low[u] = Math.min(low[u], dfn[v]);
}
}
if (low[u] == dfn[u]) {
while (true) {
int y = stk[top--];
id[y] = sccCnt;
inStk[y] = false;
if (y == u) break;
}
sccCnt++;
}
}
}
- C++
#include <iostream>
#include <vector>
using namespace std;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;
vector<int> g[N];
int low[N], dfn[N], stk[N], id[N];
bool in_stk[N];
int timestamp = 0, scc_cnt = 0, top = -1;
void tarjan(int u) {
low[u] = dfn[u] = ++timestamp;
stk[++top] = u;
in_stk[u] = true;
for (int v : g[u]) {
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (in_stk[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if (low[u] == dfn[u]) {
while (true) {
int y = stk[top--];
id[y] = scc_cnt;
in_stk[y] = false;
if (y == u) break;
}
scc_cnt++;
}
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
u--; v--;
g[v].push_back(u);
}
for (int i = 0; i < n; i++)
if (!dfn[i]) tarjan(i);
int ans = 1;
for (int i = 0; i < scc_cnt; i++)
ans = ans * 2 % MOD;
cout << (ans - 1 + MOD) % MOD << endl;
return 0;
}