美团笔试 美团笔试题 0412

笔试时间:2025年04月12日

历史笔试传送门:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题

题目:数组1.0

给定一个长度为 n 的数组 a。定义一次操作: 选择数组中的一个数,然后把这个数从数组中移除。其余元素按照原有顺序从前到后依次拼接。现在她想要知道,自己最少需要操作几次,才能使得数组中所有非空子数组的平均值均相同。子数组为从原数组中,连续的选择一段元素(可以全选、可以不选)得到的新数组。

输入描述

第一行输入一个整数 n(1 <= n <= 2 * 10^5),表示数组长度。

第二行输入 n 个整数 a_1,a_2,.....,a_n \left(1 <= a_i <= 10^9 ) 代表数组。

输出描述

一个整数,表示最少操作次数。

样例输入

3

1 2 3

样例输出

2

说明:删除任意两个元素后,数组只剩下一个元素,此时只有一个非空子数组,一定满足题意。

参考题解

要使数组中所有非空子数组的平均值均相同,关键在于保证剩余元素满足特定条件。通过分析可知,唯一满足条件的剩余数组是所有元素相同或仅剩一个元素的情况。子数组特性: 若数组中存在不同元素,则子数组的平均值必然不同。例如,数组 [a, b] 的子数组平均值为 a、b、(a+b)/2,显然无法全部相同。 因此,只有剩余元素全相同或只剩一个元素时,才能满足所有子数组的平均值相同。操作目标:情况1:保留所有相同元素。此时需删除其他元素,操作次数为 n - max_count(max_count 是出现次数最多的元素的频次)。情况2:仅保留一个元素。操作次数为 n-1。 最终答案为两者的最小值 min(n - max_count, n-1),但进一步观察可知,当 max_count ≥ 1 时,n - max_count ≤ n-1,因此答案简化为 n - max_count。

C++:[此代码未进行大量数据的测试,仅供参考]

#include <iostream>
#include <unordered_map>
using namespace std;

int main() {
    int n;
    cin >> n;
    unordered_map<int, int> cnt;
    int mx = 0;
    
    for (int i = 0; i < n; ++i) {
        int x;
        cin >> x;
        cnt[x]++;
        mx = max(mx, cnt[x]);
    }

    cout << n - mx << endl;
    return 0;
}

Java:[此代码未进行大量数据的测试,仅供参考]

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        int n = sc.nextInt();
        int[] a = new int[n];
        Map<Integer, Integer> countMap = new HashMap<>();
        
        int mx = 0;
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
            countMap.put(a[i], countMap.getOrDefault(a[i], 0) + 1);
            mx = Math.max(mx, countMap.get(a[i]));
        }
        
        System.out.println(n - mx);
    }
}

Python:[此代码未进行大量数据的测试,仅供参考]

from collections import defaultdict

n = int(input())
a = list(map(int, input().split()))
cnt = defaultdict(int)
mx = 0
for num in a:
    cnt[num] += 1
    if cnt[num] > mx:
        mx = cnt[num]
print(n - mx)

第二题

题目:小美的排列区间

小美拿到了一个数组 a,她用以下方式生成数组 b:初始b为空,随后,对于每个 a_i,依次将 1 到 a_i 这 a_i 个数添加到数组 b 的末尾。例如,对于a数组为[3,1,2],生成的b数组为:[1,2,3,1,1,2]。现在小美想知道,b数组中有多少个连续子数组为排列?连续子数组为从原数组中,连续的选择一段元素(可以全选、可以不选)得到的新数组。长度为 n 的排列是由 1 ~ n 这 n 个整数、按任意顺序组成的数组,其中每个整数恰好出现一次。例如,{2,3,1,5,4} 是一个长度为 5 的排列,而 {1,2,2} 和 {1,3,4} 都不是排列,因为前者存在重复元素,后者包含了超出范围的数。

输入描述

第一行输入一个正整数n,代表数组a的大小。

第二行输入n个正整数a_i,代表数组a的元素。

1 <= n  <= 10^51 <= a_i <= 10^9

输出描述

一个整数,代表 b 数组的全部连续子数组中,为排列的数量。

样例输入

3

3 1 2

样例输出

7

说明:[1,2,3,1,1,2]有7个连续子数组是排列:3个长度为1的,2个长度为2的,2个长度为3的。

参考题解

数据比较大,不可能直接生成数组去统计,必须利用排列的特性和题目的特殊要求进行快速求解。块内贡献:每个块生成的子数组贡献的数量等于该块的长度,因为每个块的前m个元素恰好是1到m的排列。每个块生成的序列是[1,2,...,a_i]。这些序列的每个前缀子数组[1], [1,2], ..., [1,2,...,a_i] 都是排列。 例如,a_i=3 时贡献3个排列,a_i=1 时贡献1个。 总块内贡献是 sum_a = a[0] + a[1] + ... + a[n-1]。跨块贡献:对于每对相邻的块,计算可能形成排列的连续子数组数目。这些子数组必须满足最大值等于长度,并且元素总和为1到该长度的总和。当两个相邻块生成的序列连接时,可能形成跨越两个块的排列子数组。例如:前一个块的末尾部分是 [x, x+1, ..., a_i]后一个块的开头部分是 [1, 2, ..., y]组合后的子数组 [x, x+1, ..., a_i, 1, 2, ..., y] 可能是排列。子数组的长度必须等于其最大值。例如,长度为k的排列最大值是k。假设子数组跨越前块的末尾p个元素和后块的开头q个元素,总长度k = p + q。最大值只能是前块的末尾元素(即a_i),因此需满足 k = a_i。此时后块需要提供 q = a_i - p 个元素(且 q <= a_j)。p 的最小值:max(a_i - a_j, 1)p 的最大值:a_i - 1贡献数为 max(0, (a_i-1) - max(a_i - a_j, 1) + 1)。

C++:[此代码未进行大量数据的测试,仅供参考]

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<long long> a(n);
    long long ans = 0;

    for (int i = 0; i < n; ++i) {
        cin >> a[i];
        ans += a[i];
    }

    for (int i = 0; i < n - 1; ++i) {
        long long a_i = a[i];
        long long a_j = a[i + 1];
        long long dn = max(a_i - a_j, 1LL);
        long long up = a_i - 1;
        if (dn <= up) {
            ans += up - dn + 1;
        }
    }

    cout << ans << endl;
    return 0;
}

Java:[此代码未进行大量数据的测试,仅供参考]

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int[] a = new int[n];
        long ans = 0;

        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
            ans += a[i];
        }

        for (int i = 0; i < n - 1; i++) {
            int a_i = a[i];
            int a_j = a[i + 1];
            int dn = Math.max(a_i - a_j, 1);
            int up = a_i - 1;
            if (dn <= up) {
                ans += (up - dn + 1);
            }
        }

        System.out.println(ans);
    }
}

Python:[此代码未进行大量数据的测试,仅供参考]

n = int(input

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务