选修课
难度:★★
别看代码多大部分都是输入输出,不说了,java的泪。主要还是排序。
选修课
知识点字符串哈希表排序
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
现有两门选修课,每门选修课都有一部分学生选修,每个学生都有选修课的成绩,需要你找出同时选修了两门选修课的学生,先按照班级进行划分,班级编号小的先输出,每个班级按照两门选修课成绩和的降序排序,成绩相同时按照学生的学号升序排序。
输入描述:
第一行为第一门选修课学生的成绩,第二行为第二门选修课学生的成绩,每行数据中学生之间以英文分号分隔,每个学生的学号和成绩以英文逗号分隔,学生学号的格式为8位数字(2位院系编号+入学年份后2位+院系内部1位专业编号+所在班级3位学号),学生成绩的取值范围为[0,100]之间的整数,两门选修课选修学生数的取值范围为[1-2000]之间的整数。
输出描述:
同时选修了两门选修课的学生的学号,如果没有同时选修两门选修课的学生输出NULL,否则,先按照班级划分,班级编号小的先输出,每个班级先输出班级编号(学号前五位),然后另起一行输出这个班级同时选修两门选修课的学生学号,学号按照要求排序(按照两门选修课成绩和的降序,成绩和相同时按照学号升序),学生之间以英文分号分隔。
示例1
输入:
01202021,75;01201033,95;01202008,80;01203006,90;01203088,100
01202008,70;01203088,85;01202111,80;01202021,75;01201100,88
输出:
01202
01202008;01202021
01203
01203088
说明:
同时选修了两门选修课的学生01202021、01202008、01203088,这三个学生两门选修课的成绩和分别为150、150、185,01202021、01202008属于01202班的学生,按照成绩和降序,成绩相同时按学号升序输出的结果为01202008;01202021,01203088属于01203班的学生,按照成绩和降序,成绩相同时按学号升序输出的结果为01203088,01202的班级编号小于01203的班级编号,需要先输出。
示例2
输入:
01201022,75;01202033,95;01202018,80;01203006,90;01202066,100
01202008,70;01203102,85;01202111,80;01201021,75;01201100,88
输出:
NULL
说明:
没有同时选修了两门选修课的学生,输出NULL。
解题思路:
- 使用
Scanner
对象读取输入的两门选修课学生的成绩。 - 创建一个
HashMap
用于存储选修了两门课的学生信息,其中键为班级编号,值为对应班级的学生列表。 - 遍历第一门选修课学生的成绩,并与第二门选修课学生的成绩进行比较,找到同时选修了两门课的学生。
- 将同时选修两门课的学生信息存储到对应班级的学生列表中。
- 如果没有符合要求的学生,输出"NULL"。
- 对班级进行排序,并按要求输出班级编号和学生学号。
JAVA代码:
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] one = sc.nextLine().split(";");
String[] two = sc.nextLine().split(";");
sc.close();
// 创建一个 HashMap 用于存储选修了两门课的学生信息
Map<String, List<Student>> map = new HashMap<>();
for (String score : one) {
String[] parts = score.split(",");
String studentId = parts[0];
int score1 = Integer.parseInt(parts[1]);
// 使用学生学号作为键,直接存储到 HashMap 中
map.put(studentId, new ArrayList<>());
map.get(studentId).add(new Student(studentId, score1));
}
for (String score : two) {
String[] parts = score.split(",");
String studentId = parts[0];
int score2 = Integer.parseInt(parts[1]);
// 如果学生学号存在于 HashMap 中,则更新第二门选修课成绩
if (map.containsKey(studentId)) {
map.get(studentId).get(0).score2 = score2;
}
}
List<Student> selectedStudents = new ArrayList<>();
for (List<Student> students : map.values()) {
// 将同时选修了两门课的学生添加到选中的学生列表中
if (students.get(0).score2 > 0) {
selectedStudents.addAll(students);
}
}
if (selectedStudents.isEmpty()) {
System.out.println("NULL");
} else {
// 对选中的学生列表进行排序,首先按照总成绩降序排序,然后按照学生学号升序排序
selectedStudents.sort(Comparator
.comparing(Student::getScoreSum).reversed()
.thenComparing(Student::getStudentId));
// 使用 TreeMap 对班级进行排序,保证班级编号的升序输出
Map<String, List<Student>> classMap = new TreeMap<>();
for (Student student : selectedStudents) {
String classId = student.getStudentId().substring(0, 5);
// 将学生添加到对应班级的学生列表中
classMap.putIfAbsent(classId, new ArrayList<>());
classMap.get(classId).add(student);
}
for (Map.Entry<String, List<Student>> entry : classMap.entrySet()) {
// 输出班级编号
System.out.println(entry.getKey());
StringBuilder res = new StringBuilder();
for (Student student : entry.getValue()) {
// 输出学生学号,并使用分号分隔
res.append(student.getStudentId()).append(";");
}
// 移除最后一个分号,并输出结果
System.out.println(res.substring(0, res.length() - 1));
}
}
}
// 学生类
static class Student {
String studentId; // 学生学号
int score1; // 第一门选修课成绩
int score2; // 第二门选修课成绩
public Student(String studentId, int score1) {
this.studentId = studentId;
this.score1 = score1;
this.score2 = -1; // 初始值设为 -1 表示未选修第二门课
}
public int getScoreSum() {
// 返回两门选修课成绩之和
return score1 + score2;
}
public String getStudentId() {
return studentId;
}
}
}
代码说明:
代码思路和实现说明如下:
- 首先使用
Scanner
对象从标准输入中读取两门选修课学生的成绩,分别保存在one
和two
数组中。 - 创建一个
HashMap
,用于存储选修了两门课的学生信息。键为学生的学号,值为对应学生的成绩信息。 - 遍历
one
数组,将每个学生的学号和成绩存储在HashMap
中。 - 遍历
two
数组,对于每个学生的学号,如果在HashMap
中存在,则更新该学生的第二门选修课成绩。 - 创建一个
selectedStudents
列表,用于存储同时选修了两门课的学生。 - 遍历
HashMap
中的值,如果学生的第二门选修课成绩大于0,则将该学生添加到selectedStudents
列表中。 - 如果
selectedStudents
列表为空,表示没有同时选修两门课的学生,输出"NULL"。 - 否则,对
selectedStudents
列表进行排序,首先按照总成绩降序排序,然后按照学生学号升序排序。 - 创建一个
classMap
,用于按照班级将选中的学生进行分组。 - 遍历
selectedStudents
列表,将学生按照班级编号添加到classMap
中。 - 使用
TreeMap
对classMap
进行排序,按照班级编号升序输出班级信息。 - 遍历
classMap
,输出班级编号和对应班级的学生学号。