【华为OD-E卷 - 选修课 100分(python、java、c++、js、c)】
题目
现有两门选修课,每门选修课都有一部分学生选修,每个学生都有选修课的成绩,需要你找出同时选修了两门选修课的学生,先按照班级进行划分,班级编号小的先输出,每个班级按照两门选修课成绩和的降序排序,成绩相同时按照学生的学号升序排序
输入描述
- 第一行为第一门选修课学生的成绩,
第二行为第二门选修课学生的成绩,
每行数据中学生之间以英文分号分隔,每个学生的学号和成绩以英文逗号分隔,
学生学号的格式为8位数字
2位院系编号+入学年份后2位+院系内部1位专业编号+所在班级3位学号
学生成绩的取值范围为[0,100]之间的整数,
两门选修课选修学生数的取值范围为[1-2000]之间的整数
输出描述
- 同时选修了两门选修课的学生的学号,如果没有同时选修两门选修课的学生输出NULL,
否则,先按照班级划分,班级编号小的先输出,每个班级先输出班级编号(学号前五位),
然后另起一行输出这个班级同时选修两门选修课的学生学号,学号按照要求排序(按照两门选修课成绩和的降序,成绩和相同时按照学号升序学生之间以英文分号分隔
用例
用例一:
输入:
01202021,75;01201033,95;01202008,80;01203006,90;01203088,100
01202008,70;01203088,85;01202111,80;01202021,75;01201100,88
- 1
- 2
输出:
01202
01202008;01202021
01203
01203088
- 1
- 2
- 3
- 4
用例二:
输入:
01201022,75;01202033,95;01202018,80;01203006,90;01202066,100
01202008,70;01203102,85;01202111,80;01201021,75;01201100,88
- 1
- 2
输出:
NULL
- 1
python解法
- 解题思路:
- 这道题目涉及到处理学生成绩数据并按要求输出结果。主要任务是解析输入的成绩数据、处理学生成绩,最后按一定规则进行排序输出。
主要任务分解:
数据解析: 输入的成绩数据是由学生ID和对应的分数组成的字符串,需要从中提取出学生ID、课程ID以及成绩。
数据存储: 使用学生ID来存储学生对象,学生对象需要保存学生ID、课程ID、两门课程成绩。
过滤: 只处理两门课程都已经有成绩的学生。
分组: 按照课程ID对学生进行分组。
排序: 在每个课程组内按规则排序:按学生成绩(s1 + s2 的和从大到小)排序,如果成绩相同,则按学生ID字典序升序排序。
输出结果: 输出按课程ID分组后的学生ID列表,如果没有符合条件的学生,则输出 “NULL”
s1 = input() # 读取第一门课程的学生成绩数据
s2 = input() # 读取第二门课程的学生成绩数据
# 定义学生类
class Student:
def __init__(self, sid, cid, s1, s2):
self.sid = sid # 学生ID
self.cid = cid # 课程ID
self.s1 = s1 # 第一门课程成绩
self.s2 = s2 # 第二门课程成绩
# 解析数据并将成绩分配给对应的学生对象
def parse_data(data, course_id, students):
for item in data.split(";"): # 按照分号拆分成绩数据
sid, score = item.split(",") # 学生ID与成绩用逗号分隔
cid = sid[:5] # 课程ID是学生ID的前五位字符
score = int(score) # 转换成绩为整数
# 如果学生ID不在学生字典中,则添加该学生
if sid not in students:
students[sid] = Student(sid, cid, -1, -1) # 初始成绩为-1,表示未评分
# 根据课程ID更新学生的成绩
if course_id == 1:
students[sid].s1 = score # 第一门课程成绩
else:
students[sid].s2 = score # 第二门课程成绩
# 处理结果并输出
def process_result():
students = {} # 用字典存储学生数据,以学生ID为键
# 解析两门课程的成绩数据
parse_data(s1, 1, students) # 第一门课程
parse_data(s2, 2, students) # 第二门课程
# 过滤掉没有两门课程成绩的学生
filtered_students = [stu for stu in students.values() if stu.s1 != -1 and stu.s2 != -1]
# 如果没有符合条件的学生,输出 "NULL"
if not filtered_students:
print("NULL")
return
classes = {} # 用字典按课程ID分组学生
# 将学生按照课程ID分类
for stu in filtered_students:
if stu.cid not in classes:
classes[stu.cid] = [] # 如果课程ID还没有对应的学生列表,初始化一个空列表
classes[stu.cid].append(stu) # 将学生加入对应的课程组
# 按课程ID排序,课程ID升序
for cid in sorted(classes.keys()):
print(cid) # 输出课程ID
# 对课程组内的学生进行排序:按照成绩之和降序,若相同则按学号升序
sorted_students = sorted(classes[cid], key=lambda stu: (-stu.s1 - stu.s2, stu.sid))
# 输出排序后的学生ID,使用分号连接
print(";".join([stu.sid for stu in sorted_students]))
# 执行程序
process_result()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
java解法
- 解题思路
- 本题目要求解析两门课程的学生成绩数据,找到有两门课程成绩的学生,并按要求输出。具体步骤如下:
输入数据处理:
输入包含两行数据,分别代表两门课程的成绩,格式为 学生ID,成绩;学生ID,成绩;…。
每个学生有一个唯一的学生ID(sid),每门课程成绩都有可能被录入。如果学生的两门课程成绩都已经有记录,则该学生满足输出条件。
数据存储:
使用一个 Map
学生对象 Student 中包含 sid(学生ID)、score1(第一门课程成绩)、score2(第二门课程成绩),并提供 getTotalScore() 方法来计算该学生两门课程成绩的总和。
课程分组:
对于每个学生,如果该学生两门课程成绩都已录入,则将其按课程ID分组(课程ID由学生ID的前五个字符来决定),并存入一个 Map
排序:
对每门课程的学生列表按照以下规则进行排序:
按两门课程的总成绩(score1 + score2)降序排序。
如果总成绩相同,则按学生ID字典序升序排序。
输出结果:
对每个课程,按课程ID升序输出,接着输出该课程下按排序规则排列的学生ID列表。如果没有符合条件的学生,输出 “NULL”
import java.util.*;
public class Main {
// 学生类,用于存储学生的成绩信息
static class Student {
String sid; // 学生ID
int score1 = -1; // 第一门课程成绩,初始化为-1,表示未评分
int score2 = -1; // 第二门课程成绩,初始化为-1,表示未评分
// 计算学生的总成绩
public int getTotalScore() {
return score1 + score2;
}
}
public static void main(String[] args) {
// 创建扫描器对象,用于接收输入
Scanner scanner = new Scanner(System.in);
// 读取两门课程的成绩数据
String s1 = scanner.nextLine(); // 第一门课程的成绩数据
String s2 = scanner.nextLine(); // 第二门课程的成绩数据
// 调用 findCommonStudents 方法,查找有成绩的学生,并输出结果
findCommonStudents(s1, s2);
}
// 找到有两门课程成绩的学生并按照要求输出
private static void findCommonStudents(String s1, String s2) {
// 存储所有学生的成绩信息
Map<String, Student> students = new HashMap<>();
// 处理第一门课程的成绩数据
processInput(s1, students, 1);
// 处理第二门课程的成绩数据
processInput(s2, students, 2);
// 存储课程ID到学生列表的映射
Map<String, List<Student>> classMap = new TreeMap<>();
// 对所有学生进行处理,找出有两门课程成绩的学生,并按课程ID分组
for (Student student : students.values()) {
// 只有两门课程都已经有成绩的学生才会被处理
if (student.score1 != -1 && student.score2 != -1) {
// 获取学生的课程ID(取学生ID的前五个字符)
String classId = student.sid.substring(0, 5);
// 初始化课程ID对应的学生列表
classMap.putIfAbsent(classId, new ArrayList<>());
// 将学生加入对应课程ID的列表中
classMap.get(classId).add(student);
}
}
// 如果没有符合条件的学生,输出 "NULL"
if (classMap.isEmpty()) {
System.out.println("NULL");
} else {
// 对每个课程ID,按要求输出学生列表
for (String classId : classMap.keySet()) {
// 输出课程ID
System.out.println(classId);
// 获取该课程ID下的所有学生列表
List<Student> classStudents = classMap.get(classId);
// 按总成绩降序排序,如果总成绩相同,则按学生ID升序排序
classStudents.sort((a, b) -> {
// 比较总成绩,降序排列
int compare = Integer.compare(b.getTotalScore(), a.getTotalScore());
// 如果总成绩相同,按学生ID字典序升序排列
return compare != 0 ? compare : a.sid.compareTo(b.sid);
});
// 使用 StringJoiner 格式化输出学生ID,学生ID之间用分号分隔
StringJoiner sj = new StringJoiner(";");
for (Student student : classStudents) {
sj.add(student.sid);
}
// 输出该课程的所有学生ID
System.out.println(sj);
}
}
}
// 处理输入数据并填充学生成绩信息
private static void processInput(String input, Map<String, Student> students, int courseId) {
// 按照分号分隔每个学生的成绩数据
for (String entry : input.split(";")) {
// 按逗号分隔学生ID和成绩
String[] parts = entry.split(",");
String sid = parts[0]; // 学生ID
int score = Integer.parseInt(parts[1]); // 学生成绩
// 如果学生尚未存在于 students 中,则创建并初始化该学生
students.putIfAbsent(sid, new Student());
Student student = students.get(sid);
student.sid = sid; // 设置学生ID
// 根据课程ID设置对应的成绩
if (courseId == 1) {
student.score1 = score; // 设置第一门课程成绩
} else {
student.score2 = score; // 设置第二门课程成绩
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
C++解法
- 解题思路
更新中
- 1
C解法
更新中
- 1
JS解法
更新中
- 1
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏
评论记录:
回复评论: