✅ 春招备战指南 ✅
💡 学习建议:
- 先尝试独立解题(建议用时:90分钟/套)
- 对照解析查漏补缺
- 配套练习题库
互联网必备刷题宝典🔗
📢 美团技术岗笔试重要信息速览
⏰ 笔试时间安排
- 常规场次:每周六交替进行
- 上午场 10:00~11:30
- 晚间场 19:00~20:30
- 通知时间:每周四/五通过邮箱发送考试链接
🧩 笔试题型分布
| 岗位类型 | 题目构成 |
|---|---|
| 算法岗 | 选择题 + 5道编程 |
| 后端开发岗 | 选择题 + 3道编程 |
| 前端/测试岗 | 选择题 + 2道编程 |
⚙️ 考试设置要点
- 考试平台:牛客网(ACM模式)
- 监考要求:
- 必须开启笔记本前置摄像头
- 禁止使用手机(需小程序锁定)
- 允许使用本地IDE
- 编程规范:
- 严格遵循输入输出格式
- 注意时间复杂度控制(通常1s对应1e8次运算)
📚 笔试经验贴
(所有展示题面均已进行改编处理,保留核心考点)
本题库收录整理自:
- 互联网公开的笔试真题回忆版(经网友投稿)
- 各大技术社区公开讨论的经典题型
- 历年校招考生提供的解题思路
🔍 题库特点:
- 100%真实笔试场景还原
- 包含高频考点题型
- 提供多语言实现参考
- 持续更新2024届最新真题
⚠️ 注意事项:
- 所有题目均来自公开渠道,已进行改编脱敏处理
- 实际笔试可能出现题型变化,请以官方通知为准
🚀 春招备战指南
金三银四求职季即将到来!这里整理了最新美团真题及解析,助你快速掌握笔试套路。建议重点突破以下题型:
- 数组/字符串操作
- 树形结构应用
- 贪心/动态规划
- 区间合并问题
(👇 下附最新笔试真题及详细解析 👇)
真题详解(改编版)
题目 1: 好数统计
题目描述
小基有一个长度为 n n n 的数组 a 1 , a 2 , . . . , a n {a_1,a_2,...,a_n} a1,a2,...,an,她认为一个数字是好数需要满足该数字的所有数位之和是一个偶数且至少包含一个奇数。求该数组中有多少个好数。
输入格式
第一行输入一个整数
n
n
n(
1
≤
n
≤
1
0
5
1≤n≤10^5
1≤n≤105)代表数组中的元素数量。
第二行输入
n
n
n 个整数
a
1
,
a
2
,
.
.
.
,
a
n
a_1,a_2,...,a_n
a1,a2,...,an(
1
≤
a
i
≤
1
0
9
1≤a_i≤10^9
1≤ai≤109)表示数组元素。
输出格式
输出一个整数,表示好数的个数。
样例
输入:
3
13 14 15
输出:
2
题解
遍历每个数字,将其转为字符串后统计数位和和是否包含奇数。时间复杂度 O ( n log 10 M ) O(n\log_{10}M) O(nlog10M),其中 M M M 是最大数字。
代码实现
C++:
#include <iostream>
#include <string>
using namespace std;
bool check_num(int x) {
string num = to_string(x);
int sum = 0;
bool has_odd = false;
for(char d : num) {
int digit = d - '0';
sum += digit;
if(digit % 2 == 1) has_odd = true;
}
return sum % 2 == 0 && has_odd;
}
int main() {
int n;
cin >> n;
int cnt = 0;
for(int i = 0; i < n; i++) {
int x;
cin >> x;
if(check_num(x)) cnt++;
}
cout << cnt << endl;
return 0;
}
Java:
import java.util.Scanner;
public class Main {
static boolean isGoodNum(int num) {
String str = String.valueOf(num);
int total = 0;
boolean hasOdd = false;
for(char c : str.toCharArray()) {
int d = c - '0';
total += d;
if(d % 2 == 1) hasOdd = true;
}
return total % 2 == 0 && hasOdd;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int size = scan.nextInt();
int count = 0;
for(int i = 0; i < size; i++) {
int val = scan.nextInt();
if(isGoodNum(val)) count++;
}
System.out.println(count);
}
}
Python:
def is_good_num(x: int) -> bool:
num_str = str(x)
digit_sum = sum(int(d) for d in num_str)
has_odd = any(int(d) % 2 == 1 for d in num_str)
return digit_sum % 2 == 0 and has_odd
def solve():
n = int(input())
nums = list(map(int, input().split()))
print(sum(1 for x in nums if is_good_num(x)))
if __name__ == "__main__":
solve()
题目 2: 数字提取
题目描述
小柯面前有一个混合字符串,仅由小写英文字母和数字组成。他想找出第 k k k 个数,规则如下:
- 连续数字会连成一个非负整数。
- 将所有提取出的非负整数按降序排列,选择第 k k k 个数。
- 若不存在第 k k k 个数,则输出 N N N。
输入格式
第一行输入一个正整数
k
k
k(
1
≤
k
≤
1
0
5
1≤k≤10^5
1≤k≤105)。
第二行输入一个长度不超过
1
0
5
10^5
105 的混合字符串
s
s
s。
输出格式
输出第 k k k 个数(不包含前导 0 0 0),如果不存在则输出 N N N。
样例
输入:
3
a12b03c3d0
输出:
3
说明:提取出的非负整数按降序排列为:[ 12 , 3 , 3 , 0 12,3,3,0 12,3,3,0],第 3 3 3 个数为 3 3 3。
题解
使用正则表达式或字符串处理提取数字,注意处理前导零。时间复杂度 O ( n log n ) O(n\log n) O(nlogn),其中 n n n 是字符串长度。
代码实现
C++:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int k;
string s;
cin >> k >> s;
vector<int> nums;
string curr;
for(char c : s) {
if(isdigit(c)) {
curr += c;
} else if(!curr.empty()) {
while(curr.size() > 1 && curr[0] == '0') {
curr = curr.substr(1);
}
nums.push_back(stoi(curr));
curr.clear();
}
}
if(!curr.empty()) {
while(curr.size() > 1 && curr[0] == '0') {
curr = curr.substr(1);
}
nums.push_back(stoi(curr));
}
sort(nums.begin(), nums.end(), greater<int>());
if(k > nums.size()) cout << "N" << endl;
else cout << nums[k-1] << endl;
return 0;
}
Java:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int pos = scan.nextInt();
String str = scan.next();
List<Integer> nums = new ArrayList<>();
StringBuilder curr = new StringBuilder();
for(char c : str.toCharArray()) {
if(Character.isDigit(c)) {
curr.append(c);
} else if(curr.length() > 0) {
while(curr.length() > 1 && curr.charAt(0) == '0') {
curr.deleteCharAt(0);
}
nums.add(Integer.parseInt(curr.toString()));
curr.setLength(0);
}
}
if(curr.length() > 0) {
while(curr.length() > 1 && curr.charAt(0) == '0') {
curr.deleteCharAt(0);
}
nums.add(Integer.parseInt(curr.toString()));
}
nums.sort(Collections.reverseOrder());
System.out.println(pos > nums.size() ? "N" : nums.get(pos-1));
}
}
Python:
def extract_nums(s: str) -> list:
nums = []
curr = ''
for c in s:
if c.isdigit():
curr += c
elif curr:
while len(curr) > 1 and curr[0] == '0':
curr = curr[1:]
nums.append(int(curr))
curr = ''
if curr:
while len(curr) > 1 and curr[0] == '0':
curr = curr[1:]
nums.append(int(curr))
return sorted(nums, reverse=True)
def solve():
k = int(input())
s = input()
nums = extract_nums(s)
print('N' if k > len(nums) else nums[k-1])
if __name__ == "__main__":
solve()
题目 3: 宠物对战
题目描述
小兰和小柯各有一些宠物,它们的战力分别为 a 1 , a 2 , . . . , a n {a_1,a_2,...,a_n} a1,a2,...,an 和 b 1 , b 2 , . . . , b m {b_1,b_2,...,b_m} b1,b2,...,bm。他们进行对战,规则如下:
- 双方同时随机选出一只宠物。
- 如果双方战力都为质数,双方获得 a i + b j a_i+b_j ai+bj 点提升。
- 如果一方战力为质数,双方获得 max ( a i , b j ) \max(a_i,b_j) max(ai,bj) 点提升。
- 如果都不是质数,小柯获得 a i a_i ai 点提升,小兰获得 b j b_j bj 点提升。
每只宠物最多参与一次对战,求最大可能获得的总提升点数。
输入格式
第一行输入两个整数
n
,
m
n,m
n,m(
1
≤
n
,
m
≤
100
1≤n,m≤100
1≤n,m≤100)。
第二行输入
n
n
n 个整数表示小兰的宠物战力。
第三行输入
m
m
m 个整数表示小柯的宠物战力。
输出格式
第一行输出最大提升点数。
第二行输出
n
n
n 个整数,表示小兰的每只宠物与哪只宠物对战,未参战输出
−
1
-1
−1。
样例
输入:
5 4
5 7 3 1 1
2 6 11 2
输出:
67
1 3 4 2 -1
题解
这是一个带权二分图最大匹配问题,可以使用匈牙利算法求解:
-
构建权值矩阵:
- 双方都是质数:得分为两者之和
- 一方是质数:得分为较大值
- 都不是质数:得分为各自交换
-
使用匈牙利算法找到最优匹配:
- 维护访问数组和匹配数组
- 通过 DFS 寻找增广路径
- 记录每个宠物的对战情况
时间复杂度 O ( n 3 ) O(n^3) O(n3),空间复杂度 O ( n 2 ) O(n^2) O(n2)。
代码实现
C++:
#include <iostream>
#include <vector>
#include <algorithm>
#include <limits>
using namespace std;
const long long INF = 1LL << 60;
bool check_prime(int num) {
if(num < 2) return false;
for(int d = 2; d * d <= num; d++) {
if(num % d == 0) return false;
}
return true;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// 读取输入
int size1, size2;
cin >> size1 >> size2;
vector<int> power1(size1), power2(size2);
for(int i = 0; i < size1; i++) cin >> power1[i];
for(int i = 0; i < size2; i++) cin >> power2[i];
// 构建得分矩阵
int max_size = max(size1, size2);
vector<vector<long long>> score(max_size, vector<long long>(max_size));
for(int i = 0; i < size1; i++) {
for(int j = 0; j < size2; j++) {
int val1 = power1[i], val2 = power2[j];
bool is_prime1 = check_prime(val1);
bool is_prime2 = check_prime(val2);
if(is_prime1 && is_prime2) {
score[i][j] = 2LL * (val1 + val2);
} else if(is_prime1 || is_prime2) {
score[i][j] = 2LL * max(val1, val2);
} else {
score[i][j] = val1 + val2;
}
}
}
// 匈牙利算法
vector<vector<long long>> cost(max_size, vector<long long>(max_size));
for(int i = 0; i < max_size; i++) {
for(int j = 0; j < max_size; j++) {
cost[i][j] = -score[i][j];
}
}
vector<long long> u(max_size + 1), v(max_size + 1);
vector<int> match(max_size + 1), way(max_size + 1);
for(int i = 1; i <= max_size; i++) {
match[0] = i;
vector<long long> min_val(max_size + 1, INF);
vector<bool> used(max_size + 1, false);
int j1 = 0;
do {
used[j1] = true;
int i1 = match[j1], j2 = 0;
long long delta = INF;
for(int j = 1; j <= max_size; j++) {
if(!used[j]) {
long long cur = cost[i1-1][j-1] - u[i1] - v[j];
if(cur < min_val[j]) {
min_val[j] = cur;
way[j] = j1;
}
if(min_val[j] < delta) {
delta = min_val[j];
j2 = j;
}
}
}
for(int j = 0; j <= max_size; j++) {
if(used[j]) {
u[match[j]] += delta;
v[j] -= delta;
} else {
min_val[j] -= delta;
}
}
j1 = j2;
} while(match[j1] != 0);
do {
int j2 = way[j1];
match[j1] = match[j2];
j1 = j2;
} while(j1);
}
// 输出结果
vector<int> result(size1, -1);
for(int j = 1; j <= max_size; j++) {
if(match[j] <= size1 && j <= size2) {
result[match[j]-1] = j-1;
}
}
long long total = 0;
for(int i = 0; i < size1; i++) {
if(result[i] != -1) total += score[i][result[i]];
}
cout << total << "\n";
for(int i = 0; i < size1; i++) {
cout << (result[i] != -1 ? result[i] + 1 : -1) << (i == size1-1 ? "\n" : " ");
}
return 0;
}
Java:
import java.util.*;
public class Main {
static final long INF = Long.MAX_VALUE / 2;
static boolean isPrime(int num) {
if(num < 2) return false;
for(int d = 2; d * d <= num; d++) {
if(num % d == 0) return false;
}
return true;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int size1 = scan.nextInt();
int size2 = scan.nextInt();
int[] power1 = new int[size1];
int[] power2 = new int[size2];
for(int i = 0; i < size1; i++) power1[i] = scan.nextInt();
for(int i = 0; i < size2; i++) power2[i] = scan.nextInt();
int maxSize = Math.max(size1, size2);
long[][] score = new long[maxSize][maxSize];
for(int i = 0; i < size1; i++) {
for(int j = 0; j < size2; j++) {
boolean prime1 = isPrime(power1[i]);
boolean prime2 = isPrime(power2[j]);
if(prime1 && prime2) {
score[i][j] = 2L * (power1[i] + power2[j]);
} else if(prime1 || prime2) {
score[i][j] = 2L * Math.max(power1[i], power2[j]);
} else {
score[i][j] = power1[i] + power2[j];
}
}
}
long[][] cost = new long[maxSize][maxSize];
for(int i = 0; i < maxSize; i++) {
for(int j = 0; j < maxSize; j++) {
cost[i][j] = -score[i][j];
}
}
long[] u = new long[maxSize + 1];
long[] v = new long[maxSize + 1];
int[] match = new int[maxSize + 1];
int[] way = new int[maxSize + 1];
for(int i = 1; i <= maxSize; i++) {
match[0] = i;
long[] minVal = new long[maxSize + 1];
Arrays.fill(minVal, INF);
boolean[] used = new boolean[maxSize + 1];
int j1 = 0;
do {
used[j1] = true;
int i1 = match[j1], j2 = 0;
long delta = INF;
for(int j = 1; j <= maxSize; j++) {
if(!used[j]) {
long curr = cost[i1-1][j-1] - u[i1] - v[j];
if(curr < minVal[j]) {
minVal[j] = curr;
way[j] = j1;
}
if(minVal[j] < delta) {
delta = minVal[j];
j2 = j;
}
}
}
for(int j = 0; j <= maxSize; j++) {
if(used[j]) {
u[match[j]] += delta;
v[j] -= delta;
} else {
minVal[j] -= delta;
}
}
j1 = j2;
} while(match[j1] != 0);
do {
int j2 = way[j1];
match[j1] = match[j2];
j1 = j2;
} while(j1 != 0);
}
int[] result = new int[size1];
Arrays.fill(result, -1);
for(int j = 1; j <= maxSize; j++) {
if(match[j] <= size1 && j <= size2) {
result[match[j]-1] = j-1;
}
}
long total = 0;
for(int i = 0; i < size1; i++) {
if(result[i] != -1) total += score[i][result[i]];
}
System.out.println(total);
for(int i = 0; i < size1; i++) {
System.out.print((result[i] != -1 ? result[i] + 1 : -1) +
(i == size1-1 ? "\n" : " "));
}
}
}
Python:
def is_prime(num: int) -> bool:
if num < 2:
return False
for d in range(2, int(num ** 0.5) + 1):
if num % d == 0:
return False
return True
def solve():
size1, size2 = map(int, input().split())
power1 = list(map(int, input().split()))
power2 = list(map(int, input().split()))
max_size = max(size1, size2)
score = [[0] * max_size for _ in range(max_size)]
# 构建得分矩阵
for i in range(size1):
for j in range(size2):
prime1 = is_prime(power1[i])
prime2 = is_prime(power2[j])
if prime1 and prime2:
score[i][j] = 2 * (power1[i] + power2[j])
elif prime1 or prime2:
score[i][j] = 2 * max(power1[i], power2[j])
else:
score[i][j] = power1[i] + power2[j]
# 匈牙利算法
INF = float('inf')
cost = [[-x for x in row] for row in score]
u = [0] * (max_size + 1)
v = [0] * (max_size + 1)
match = [0] * (max_size + 1)
way = [0] * (max_size + 1)
for i in range(1, max_size + 1):
match[0] = i
min_val = [INF] * (max_size + 1)
used = [False] * (max_size + 1)
j1 = 0
while True:
used[j1] = True
i1 = match[j1]
delta = INF
j2 = 0
for j in range(1, max_size + 1):
if not used[j]:
curr = cost[i1-1][j-1] - u[i1] - v[j]
if curr < min_val[j]:
min_val[j] = curr
way[j] = j1
if min_val[j] < delta:
delta = min_val[j]
j2 = j
for j in range(max_size + 1):
if used[j]:
u[match[j]] += delta
v[j] -= delta
else:
min_val[j] -= delta
j1 = j2
if match[j1] == 0:
break
while j1:
j2 = way[j1]
match[j1] = match[j2]
j1 = j2
# 输出结果
result = [-1] * size1
for j in range(1, max_size + 1):
if match[j] <= size1 and j <= size2:
result[match[j]-1] = j-1
total = sum(score[i][result[i]] for i in range(size1) if result[i] != -1)
print(total)
print(*[x+1 if x != -1 else -1 for x in result])
if __name__ == "__main__":
solve()

5483

被折叠的 条评论
为什么被折叠?



