【华为OD-E卷-字符串重新排序 字符串重新排列 100分(python、java、c++、js、c)】
题目
给定一个字符串s,s包括以空格分隔的若干个单词,请对s进行如下处理后输出:
1、单词内部调整:对每个单词字母重新按字典序排序
2、单词间顺序调整:
1)统计每个单词出现的次数,并按次数降序排列
2)次数相同,按单词长度升序排列
3)次数和单词长度均相同,按字典升序排列
请输出处理后的字符串,每个单词以一个空格分隔。
输入描述
- 一行字符串,每个字符取值范围:[a-zA-z0-9]以及空格,字符串长度范围:[1,1000]
输出描述
- 输出处理后的字符串,每个单词以一个空格分隔
用例
用例一:
输入:
This is an apple
输出:
an is This aelpp
用例二:
输入:
My sister is in the house not in the yard
输出:
in in eht eht My is not adry ehosu eirsst
python解法
- 解题思路:
- 本题要求对一组单词进行排序。排序的规则是:
按照每个单词的出现频率从高到低排序。
如果多个单词出现的频率相同,则按单词长度从短到长排序。
如果频率和长度都相同,则按字典序(即字母顺序)排序。
解题步骤
标准化单词:
先将每个单词的字母排序,以消除字母顺序对结果的影响。例如,“abc” 和 “cab” 都变成 “abc”。
统计单词频率:
使用 defaultdict(int) 来记录每个标准化单词的出现次数。
排序规则:
对列表进行排序时,使用自定义的排序规则:
主要按频率从高到低排序。
次要按长度从短到长排序。
最后按字典序排序。
返回结果:
最终,返回排序后的单词列表,用空格连接起来。
from collections import defaultdict
# 定义排序函数
def sort_words(lst):
# 对每个单词按字母排序(标准化处理)
lst = ["".join(sorted(w)) for w in lst]
# 使用defaultdict记录每个标准化后的单词出现的次数
cnt = defaultdict(int)
# 手动计数每个单词的出现次数
for w in lst:
cnt[w] += 1
# 按照自定义的排序规则排序单词
# 1. 按照出现频率从高到低(-cnt[x])
# 2. 按照单词的长度从短到长(len(x))
# 3. 按照字典序从小到大(x)
lst.sort(key=lambda x: (-cnt[x], len(x), x))
# 返回排序后的单词列表,单词之间用空格连接
return " ".join(lst)
# 读取输入的单词列表
words = input().split()
# 调用排序函数并输出结果
print(sort_words(words))
java解法
- 解题思路
- 本题的目的是对给定的一组单词进行排序,排序规则如下:
按照单词出现的频率从高到低进行排序。
如果多个单词的频率相同,则按单词的长度从短到长排序。
如果频率和长度都相同,则按字典序(即字母顺序)排序。
具体步骤:
标准化单词:首先对每个单词中的字母进行排序。这样,不同字母顺序的单词将会被视为相同。例如,“abc”、“bca”、“cab” 都会被转换为 “abc”。
统计单词频率:使用 TreeMap 来记录每个标准化后的单词的出现次数。TreeMap 会根据字母顺序对单词进行自动排序,但在本题中并不依赖于它的自然顺序,主要用于统计。
自定义排序规则:根据以下优先级对单词进行排序:
频率:出现次数较多的单词排在前面。
长度:出现次数相同的情况下,按单词的长度从短到长排序。
字典序:如果频率和长度都相同,按字典顺序排序。
生成排序结果:最后根据排序后的顺序构建输出字符串。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
System.out.println(processWords(input)); // 调用处理单词的方法并输出结果
}
// 处理单词的函数
public static String processWords(String s) {
// 按空格分割输入字符串,得到所有单词
String[] words = s.split(" ");
// 使用 TreeMap 来统计每个标准化单词出现的次数
// TreeMap 会按照字典序存储键(标准化后的单词)
Map<String, Integer> countMap = new TreeMap<>();
// 遍历每个单词,进行字母排序后存储到 TreeMap 中
for (String word : words) {
// 将单词转换为字符数组,并排序
char[] chars = word.toCharArray();
Arrays.sort(chars); // 排序字母
String sortedWord = new String(chars); // 转换回字符串
// 使用 getOrDefault 方法统计该标准化单词的出现次数
countMap.put(sortedWord, countMap.getOrDefault(sortedWord, 0) + 1);
}
// 将 countMap 的条目转为列表,方便自定义排序
List<Map.Entry<String, Integer>> entryList = new ArrayList<>(countMap.entrySet());
// 自定义排序规则:
// 1. 按照频率降序排序
// 2. 如果频率相同,按单词长度升序排序
// 3. 如果频率和长度都相同,按字典序排序
entryList.sort((a, b) -> {
if (!b.getValue().equals(a.getValue())) {
return b.getValue() - a.getValue(); // 按频率降序
} else {
// 如果频率相同,按长度升序
return a.getKey().length() - b.getKey().length() != 0 ? a.getKey().length() - b.getKey().length() : a.getKey().compareTo(b.getKey());
}
});
// 使用 StringBuilder 拼接结果
StringBuilder result = new StringBuilder();
for (Map.Entry<String, Integer> entry : entryList) {
// 按照频率输出每个单词,输出时每个单词后加空格
for (int i = 0; i < entry.getValue(); i++) {
result.append(entry.getKey()).append(" ");
}
}
// 去掉最后一个空格并返回结果
return result.toString().trim();
}
}
C++解法
- 解题思路
- 本题要求对输入的一组单词进行排序,排序规则如下:
频率排序:按照单词的出现频率,从高到低排序。
长度排序:如果两个单词的频率相同,按单词的长度,从短到长排序。
字典序排序:如果频率和长度都相同,则按字典序排序。
具体步骤:
标准化单词:每个单词需要进行字母排序。这样不同字母顺序的单词被视为相同,例如,“abc”和“cab”都应该视为“abc”。
统计单词的频率:使用 unordered_map 统计标准化后的单词出现的次数。
排序:对单词列表按照以下规则进行排序:
首先按出现频率降序排序。
如果频率相同,按单词的长度升序排序。
如果频率和长度都相同,按字典序排序。
输出排序后的结果:最终输出排序后的单词列表,用空格分隔
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <sstream>
using namespace std;
// 用于排序每个单词中的字母
void reorder(string &t) {
sort(t.begin(), t.end()); // 对字符串中的字母进行排序
}
int main() {
string line;
getline(cin, line); // 读取整行输入
stringstream strStream(line); // 将输入的字符串转换为 stringstream 流,方便逐个单词读取
string token;
vector<string> list; // 用于存储处理后的单词列表
unordered_map<string, int> frequency; // 用于存储每个标准化单词的出现频率
// 逐个单词读取,并进行字母排序,统计频率
while (strStream >> token) {
reorder(token); // 对单词中的字母进行排序
list.push_back(token); // 将排序后的单词加入列表
frequency[token]++; // 统计该单词的出现次数
}
// 对单词列表进行排序,排序规则:
// 1. 按照单词频率降序排序
// 2. 如果频率相同,按单词长度升序排序
// 3. 如果频率和长度都相同,按字典序排序
stable_sort(list.begin(), list.end(), [&](const string &s1, const string &s2) {
if (frequency[s1] != frequency[s2]) {
return frequency[s1] > frequency[s2]; // 频率较高的排在前面
} else if (s1.size() != s2.size()) {
return s1.size() < s2.size(); // 长度较短的排在前面
} else {
return s1 < s2; // 如果频率和长度都相同,则按字典序排序
}
});
// 输出排序后的单词列表,单词之间用空格分隔
for (size_t i = 0; i < list.size(); ++i) {
cout << list[i];
if (i < list.size() - 1) {
cout << " "; // 如果不是最后一个单词,添加空格
}
}
return 0;
}
C解法
更新中
JS解法
频率排序:单词的排序首先依赖于它们的出现频率,从高到低排序。
长度排序:如果两个单词的频率相同,按单词的长度从短到长排序。
字典序排序:如果频率和长度都相同,按字典序排序。
详细步骤:
标准化单词:将每个单词中的字母按字典顺序排序。这样不同字母顺序的单词将被视为相同(例如,“abc”和“cab”会都被标准化为“abc”)。
统计单词的频率:使用 Map 来统计每个标准化单词的出现次数。
排序:对单词列表进行排序,排序规则是:
按出现频率降序排序。
如果频率相同,则按单词的长度升序排序。
如果频率和长度都相同,则按字典序排序。
输出结果:输出排序后的单词列表,用空格分隔。
// 用于将单词中的字符按字典顺序排序
function reorder(t) {
return t.split('').sort().join(''); // 将单词转换为字符数组,排序后再连接成字符串
}
// 主处理函数
function processWords(input) {
// 将输入字符串按空格分割成单词
const words = input.split(' ');
// 使用 Map 存储每个标准化单词的出现次数
const countMap = new Map();
// 遍历每个单词
for (let word of words) {
const sortedWord = reorder(word); // 将单词中的字母排序
// 更新 Map 中的频率计数
countMap.set(sortedWord, (countMap.get(sortedWord) || 0) + 1);
}
// 将 Map 转换为数组,以便进行排序
const entryList = Array.from(countMap.entries());
// 对 entries 进行排序
entryList.sort((a, b) => {
// 如果频率不同,按频率降序排序
if (b[1] !== a[1]) {
return b[1] - a[1];
}
// 如果频率相同,按单词的长度升序排序
else if (a[0].length !== b[0].length) {
return a[0].length - b[0].length;
}
// 如果频率和长度都相同,按字典序排序
else {
return a[0].localeCompare(b[0]);
}
});
// 按照排序结果构建最终输出
const result = [];
for (let [key, value] of entryList) {
for (let i = 0; i < value; i++) {
result.push(key); // 每个标准化单词按照出现次数加入结果
}
}
return result.join(' '); // 用空格连接并返回最终结果
}
// 主函数:读取输入并输出结果
function main() {
// 从标准输入中读取数据并处理
const line = require('fs').readFileSync('/dev/stdin', 'utf-8').trim();
console.log(processWords(line)); // 调用处理函数并输出结果
}
// 调用主函数
main();
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏