美团笔试 美团开发笔试 0809
笔试时间:2025年8月9日
往年笔试合集:
第一题:字符串min-15
称一个字符串为「完全不协调」,当且仅当:对于任意一种字母,其在字符串中仅有大写或仅有小写形式;对于任意一种字母(不分大小写),其都在字符串中出现过。现在,给定一个长度为 ( n )、仅由大小写字母构成的字符串 ( s )。你需要求解使其变为「完全不协调」需要的最少操作轮数 ( x )。其中,每一轮操作从以下两个方法中选择一个执行:方法一:任选一个字母(大写或小写),将其插入到字符串的任意位置(包括开头和末尾)。方法二:选择一个位于字符串中的字符,将其删除。然而,小美对数字并不感兴趣,她想知道:通过 ( x ) 轮操作能得到的字典序最小的「完全不协调」字符串是什么?【名词解释】 从字符串的第一个字符开始逐个比较,直至发现第一个不同的位置,比较这个位置字符的 ASCII 码,ASCII 码较小(‘A’ < ‘B’ … < ‘Z’ < ‘a’ < … < ‘z’)的字符串字典序也较小;如果比较到其中一个字符串的结尾时依旧全部相同,则较短的字符串字典序更小。
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数 ( T )(( 1 \le T \le 10^5 ))代表数据组数,每组测试数据描述如下: 第一行输入一个整数 ( n )(( 1 \le n \le 10^5 )),表示原字符串长度; 第二行输入一个长度为 ( n ) 的字符串 ( s ),仅由大小写字母构成。 除此之外,保证单个测试文件的 ( n ) 之和不超过 ( 10^5 )。
输出描述
对于每一组测试数据,新起一行。输出一个字符串,表示 ( x ) 轮操作能得到的字典序最小的「完全不协调」字符串。
样例输入
5
26
abcdefGHIjklmnopqrstuvwxyY
8
CAECGEHG
10
MZbMwEyYdI
20
DTLCOUegMDByFWUrPwBp
19
LKGkheSppLQSsAImtll
样例输出
ZabcdefGHIjklmnopqrstuvwxY
BCADECFGEHGIJKLMNOPQRSTUVWXYZ
ACFGHJKLMNOPQRSTUVXZbMwEYdI
ADHIJKNQSTLCOUVXZegMDByFUrPwB
BCDFGJNORUVWXYZkheSppQSAImtll
说明:对于第一组测试数据,删除了 ( y ) 并在字符串首增加了 ( Z )。
参考题解
统计字母出现情况:首先统计字符串中每个字母的出现情况(大小写分开统计),并确定哪些字母已经存在(无论大小写)。 确定缺失字母:找出所有缺失的字母(即26个字母中未出现的字母)。 处理现有字母的大小写统一:对于每个已经存在的字母,统一成大写或小写。为了使字典序最小,优先选择小写字母,因为小写字母的ASCII码比大写字母大,但若该字母的大写形式在字符串中已经存在,则必须统一成大写。 插入缺失字母:将缺失的字母插入到字符串中。为了使字典序最小,插入的字母应尽可能放在前面,特别是大写字母(因为大写字母的ASCII码较小)。具体来说,插入的大写字母应放在比它大的字符前面,而小写字母应放在合适的位置以保持字典序最小。
C++:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
string solve(string s) {
// 统计每个字母的大小写出现次数
vector<int> upper(26, 0), lower(26, 0);
for (char c : s) {
if (c >= 'A' && c <= 'Z') {
upper[c - 'A']++;
} else {
lower[c - 'a']++;
}
}
// 决定每个字母使用大写还是小写
vector<bool> useUpper(26);
string result = "";
for (int i = 0; i < 26; i++) {
if (upper[i] == 0 && lower[i] == 0) {
// 字母未出现,需要添加,优先使用大写(字典序更小)
useUpper[i] = true;
} else if (upper[i] > 0 && lower[i] > 0) {
// 同时有大小写,保留数量多的
if (upper[i] >= lower[i]) {
useUpper[i] = true;
} else {
useUpper[i] = false;
}
} else {
// 只有一种形式,保留现有的
useUpper[i] = (upper[i] > 0);
}
}
// 构建结果字符串
// 先添加原字符串中需要保留的字符
for (char c : s) {
int idx;
bool isUpper = (c >= 'A' && c <= 'Z');
if (isUpper) {
idx = c - 'A';
if (useUpper[idx]) {
result += c;
}
} else {
idx = c - 'a';
if (!useUpper[idx]) {
result += c;
}
}
}
// 添加缺失的字母
for (int i = 0; i < 26; i++) {
if (upper[i] == 0 && lower[i] == 0) {
result += (char)('A' + i);
}
}
// 排序以获得字典序最小
sort(result.begin(), result.end());
return result;
}
int main() {
int T;
cin >> T;
while (T--) {
int n;
string s;
cin >> n >> s;
cout << solve(s) << endl;
}
return 0;
}
Java:
import java.util.*;
import java.io.*;
public class Solution {
public static String solve(String s) {
// 统计每个字母的大小写出现次数
int[] upper = new int[26];
int[] lower = new int[26];
for (char c : s.toCharArray()) {
if (c >= 'A' && c <= 'Z') {
upper[c - 'A']++;
} else {
lower[c - 'a']++;
}
}
// 决定每个字母使用大写还是小写
boolean[] useUpper = new boolean[26];
StringBuilder result = new StringBuilder();
for (int i = 0; i < 26; i++) {
if (upper[i] == 0 && lower[i] == 0) {
// 字母未出现,需要添加,优先使用大写
useUpper[i] = true;
} else if (upper[i] > 0 && lower[i] > 0) {
// 同时有大小写,保留数量多的
if (upper[i] >= lower[i]) {
useUpper[i] = true;
} else {
useUpper[i] = false;
}
} else {
// 只有一种形式,保留现有的
useUpper[i] = (upper[i] > 0);
}
}
// 构建结果字符串
// 先添加原字符串中需要保留的字符
for (char c : s.toCharArray()) {
int idx;
boolean isUpper = (c >= 'A' && c <= 'Z');
if (isUpper) {
idx = c - 'A';
if (useUpper[idx]) {
result.append(c);
}
} else {
idx = c - 'a';
if (!useUpper[idx]) {
result.append(c);
}
}
}
// 添加缺失的字母
for (int i = 0; i < 26; i++) {
if (upper[i] == 0 && lower[i] == 0) {
result.append((char)('A' + i));
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南
