算法每一题,成长每一天~
C0E27 智能成绩表
真题链接:【持续更新】2024华为 OD 机试E卷 机考真题库清单(全真题库)
思路
Java
import java.util.*;
public class C0E27 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] split = in.nextLine().split(" ");
int n = Integer.parseInt(split[0]); // 学生
int m = Integer.parseInt(split[1]); // 课程
String[] subjects = in.nextLine().split(" ");
assert subjects.length == m;
String[] students = new String[n];
for (int i = 0; i < n; i++) {
students[i] = in.nextLine();
}
String target = in.nextLine();
int index = -1;
for (int i = 0; i < subjects.length; i++) {
if (subjects[i].equals(target)) {
index = i; // 找到目标课程,如果找不到,表示按总分排名
break;
}
}
// 收集成绩
Map<String, Integer> map = new HashMap<>();
for (String scores : students) {
String[] stuScores = scores.split(" ");
String name = stuScores[0];
int score = 0;
if (index == -1) {
// 计算总分
for (int i = 0; i < m; i++) {
score += Integer.parseInt(stuScores[i + 1]);
}
} else {
score = Integer.parseInt(stuScores[index + 1]);
}
map.put(name, score);
}
// 排序
List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
list.sort((o1, o2) -> {
int result = o2.getValue().compareTo(o1.getValue()); // 成绩大到小
if (result != 0) {
return result;
}
return o1.getKey().compareTo(o2.getKey()); // 按姓名自然排序
});
for (Map.Entry<String, Integer> entry : list) {
System.out.print(entry.getKey() + " ");
}
}
}
总结
1、前面的思路,只考虑了按 分数 排序,没有考虑分数相同的情况。题目中有 “分数相同时按姓名排序” 这里。所以用TreeMap有问题,TreeMap只能根据key进行排序,且相同的key会覆盖!!
2、所以排序改用 list.sort() 自定义Comparator 来实现。
xx:复习 TreeMap
TreeMap 特性
- 基于红黑树实现:红黑树的特性保证了插入、删除、查找操作的时间复杂度均为 O(log n)。
- 有序的键集合:TreeMap 的键(Key)默认按照自然顺序(升序)排序,例如整数从小到大、字符串按字典序。可以通过自定义
Comparator
指定键的排序规则。- 键不允许重复:如果插入重复键,新值会覆盖旧值。
- 线程不安全的:多线程环境下需手动同步,或使用Collections.synchronizedSortedMap() 包装。
算法要多练多练多练!!