#P3067. 字符统计及重排(100分)
-
1000ms
Tried: 211
Accepted: 50
Difficulty: 3
所属公司 :
华为od
-
算法标签>排序算法
字符统计及重排(100分)
题面描述:
请编写一个程序,统计输入字符串中各个字母(区分大小写)出现的次数,并按照字母出现次数从大到小的顺序输出结果。如果出现次数相同,则按照字母的自然顺序排序,且小写字母排在大写字母之前。输出格式要求为每个字母及其出现次数用英文冒号分隔,各组之间用英文分号分隔,且末尾也需要有分号。
思路:
按照题意排序即可,先按照出现次数多少来排序,次数一样时优先小写字母并且优先ASCII码小的排序。
题解
-
输入和输出:
- 输入:一个仅包含字母的字符串(不含空格)。
- 输出:按照字母出现次数从大到小的顺序,每个字母及其出现次数用英文冒号分隔,各组之间用英文分号分隔,末尾也需要有分号。
-
步骤分析:
- 字符计数:使用一个
map<char, int>来统计字符串中每个字母的出现次数。这里,字母作为键,出现次数作为值。 - 存储数据:将
map中的键值对存储到一个vector<pair<char, int>>中,以便进行排序。 - 排序规则:
- 首先,根据字母的出现次数进行降序排序。
- 如果出现次数相同,则比较字母的 ASCII 值,确保小写字母排在大写字母之前。
- 在比较相同字母时,保持原有顺序。
- 字符计数:使用一个
-
排序实现:
- 使用
std::sort对vector进行排序,并定义自定义的比较函数。该函数首先比较次数,其次处理字母的大小写优先级。
- 使用
-
输出结果:
- 遍历排序后的
vector,按照要求格式输出结果,确保每个部分之间用分号分隔,并在末尾添加一个分号。
- 遍历排序后的
cpp
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
string input;
cin >> input; // 读取输入字符串
map<char, int> countMap; // 用于存储字母及其出现次数
// 统计字母出现次数
for (char ch : input) {
countMap[ch]++;
}
// 将字母及其次数存入 vector 中,以便排序
vector<pair<char, int>> countVec(countMap.begin(), countMap.end());
// 自定义排序规则
sort(countVec.begin(), countVec.end(), [](const pair<char, int>& a, const pair<char, int>& b) {
if (a.second != b.second) {
return a.second > b.second; // 按出现次数降序
}
// 次数相同,小写字母在前,大写字母在后
if (a.first == b.first) {
return false; // 相同的字母保持原顺序
}
// 这里用简单的条件来确保小写在前
return (isupper(a.first) && islower(b.first)) ? false : (islower(a.first) && isupper(b.first)) ? true : a.first < b.first;
});
// 输出结果
for (const auto& p : countVec) {
cout << p.first << ":" << p.second << ";";
}
return 0;
}
python
import functools
# 输入获取
s = input()
def cmp(a, b):
# 首先根据出现次数进行比较
if a[1] != b[1]:
return b[1] - a[1]
# 若出现次数相同,按字母的自然顺序进行排序
if (a[0].islower() and b[0].islower()) or (a[0].isupper() and b[0].isupper()):
return (a[0] > b[0]) - (a[0] < b[0]) # 自然顺序比较
else:
return (a[0].isupper() > b[0].isupper()) - (a[0].isupper() < b[0].isupper()) # 小写优先
# 算法入口
def getResult():
letter = {}
# 统计字母出现次数
for c in s:
letter[c] = letter.get(c, 0) + 1
letterList = list(letter.items())
# 使用自定义比较函数进行排序
letterList.sort(key=functools.cmp_to_key(cmp))
# 生成输出字符串
return "".join(f"{x[0]}:{x[1]};" for x in letterList)
# 算法调用
print(getResult())
java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine(); // 输入获取
System.out.println(getResult(s)); // 调用结果函数
}
// 自定义比较器
private static Comparator<Map.Entry<Character, Integer>> cmp = new Comparator<Map.Entry<Character, Integer>>() {
@Override
public int compare(Map.Entry<Character, Integer> a, Map.Entry<Character, Integer> b) {
// 首先根据出现次数进行比较
if (!a.getValue().equals(b.getValue())) {
return b.getValue().compareTo(a.getValue());
}
// 若出现次数相同,按字母的自然顺序进行排序
if (Character.isLowerCase(a.getKey()) && Character.isLowerCase(b.getKey()) ||
Character.isUpperCase(a.getKey()) && Character.isUpperCase(b.getKey())) {
return a.getKey().compareTo(b.getKey()); // 自然顺序比较
} else {
return Character.isUpperCase(a.getKey()) ? 1 : -1; // 小写优先
}
}
};
// 算法入口
private static String getResult(String s) {
Map<Character, Integer> letterCount = new HashMap<>();
// 统计字母出现次数
for (char c : s.toCharArray()) {
letterCount.put(c, letterCount.getOrDefault(c, 0) + 1);
}
// 将 Map 转换为 List 以便排序
List<Map.Entry<Character, Integer>> letterList = new ArrayList<>(letterCount.entrySet());
letterList.sort(cmp); // 使用自定义比较器进行排序
// 生成输出字符串
StringBuilder result = new StringBuilder();
for (Map.Entry<Character, Integer> entry : letterList) {
result.append(entry.getKey()).append(":").append(entry.getValue()).append(";"); // 构造输出格式
}
return result.toString();
}
}
题目内容
给出一个仅包含字母的字符串,不包含空格,统计字符串中各个字母(区分大小写)出现的次数,并按照字母出现次数从大到小的顺序。
输出各个字母及其出现次数。如果次数相同,按照自然顺序进行排序,且小写字母在大写字母之前。
输入描述
输入一行,为一个仅包含字母的字符串。
输出描述
按照字母出现次数从大到小的顺序输出各个字母和字母次数,用英文分号分隔,注意末尾的分号;
字母和次数间用英文冒号分隔。
样例1
输入
xyxyXX
输出
x:2;y:2;X:2;
说明
每个字符出现的个数都是2,故x排在y之前,而小写字母x在X之前
样例2
输入
abababb
输出
b:4;a:3;
说明
b的出现个数比a多,故b排在a之前