【备战春招必看】美团2025届春招第4套笔试解析 | 大厂真题通关指南

✅ 春招备战指南 ✅

💡 学习建议:

  • 先尝试独立解题(建议用时:90分钟/套)
  • 对照解析查漏补缺
  • 配套练习题库

互联网必备刷题宝典🔗

📢 美团技术岗笔试重要信息速览

⏰ 笔试时间安排

  • 常规场次:每周六交替进行
    • 上午场 10:00~11:30
    • 晚间场 19:00~20:30
  • 通知时间:每周四/五通过邮箱发送考试链接

🧩 笔试题型分布

岗位类型题目构成
算法岗选择题 + 5道编程
后端开发岗选择题 + 3道编程
前端/测试岗选择题 + 2道编程

⚙️ 考试设置要点

  • 考试平台:牛客网(ACM模式)
  • 监考要求
    • 必须开启笔记本前置摄像头
    • 禁止使用手机(需小程序锁定)
    • 允许使用本地IDE
  • 编程规范
    • 严格遵循输入输出格式
    • 注意时间复杂度控制(通常1s对应1e8次运算)

📚 笔试经验贴

(所有展示题面均已进行改编处理,保留核心考点)

本题库收录整理自:

  1. 互联网公开的笔试真题回忆版(经网友投稿)
  2. 各大技术社区公开讨论的经典题型
  3. 历年校招考生提供的解题思路

🔍 题库特点:

  • 100%真实笔试场景还原
  • 包含高频考点题型
  • 提供多语言实现参考
  • 持续更新2024届最新真题

⚠️ 注意事项:

  1. 所有题目均来自公开渠道,已进行改编脱敏处理
  2. 实际笔试可能出现题型变化,请以官方通知为准

🚀 春招备战指南

金三银四求职季即将到来!这里整理了最新美团真题及解析,助你快速掌握笔试套路。建议重点突破以下题型:

  1. 数组/字符串操作
  2. 树形结构应用
  3. 贪心/动态规划
  4. 区间合并问题

(👇 下附最新笔试真题及详细解析 👇)


真题详解(改编版)

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(1k710) x , y ( − 120 ≤ x , y ≤ 120 ) x,y(-120\le x,y\le 120) x,y(120x,y120)(保证输入合法,即保证算出的答案一定是正整数)。

输出描述

输出包含三个非负整数 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+(ax)+(ay)=k,从而推导出 a = k − y + x 3 a=\frac{k-y+x}{3} a=3ky+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 1n2×105
1 ≤ a i ≤ 1 0 9 1\le a_i\le 10^9 1ai109

输出描述

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 1n200000

输出描述

输出一个整数表示答案,由于答案可能很大,请输出答案对 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 1n,m105
1 ≤ u , v ≤ n 1\leq u,v \leq n 1u,vn
保证每个人最多只会暗恋一个人。

样例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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值