一. 题目-智能成绩表
小明来到学校当老师,需要将学生按考试总分或单科分数进行排名,你能帮帮他吗?
输入描述
第 1 11 行输入两个整数,学生人数 n nn 和科目数量 m mm。($0 < n < 100,0 < m < 10 $)
第 2 22 行输入 m mm 个科目名称,彼此之间用空格隔开。科目名称只由英文字母构成,单个长度不超过 10 1010 个字符,科目的出现顺序和后续输入的学生成绩一一对应,不会出现重复的科目名称。
第 3 33 行开始的 n nn 行,每行包含一个学生的姓名和该生 m mm 个科目的成绩(空格隔开),学生不会重名。学生的姓名只由英文字母构成,长度不超过 10 1010 个字符。成绩是 0 100 0~1000 100的整数,依次对应第 2 22 行输入的科目
第 n + 2 n + 2n+2 行,输入用作排名的科目名称,若科目不存在,则按总分进行排序。
输出描述
输出一行,按成绩排序后的学生名字,空格隔开,成绩相同的按照学生的姓名字典顺序进行排序。
样例1
输入
3 2
yuwen shuxue
fangfang 95 90
xiaohua 88 98
minmin 100 82
shuxue
1
2
3
4
5
6
输出
xiaohua fangfang minmin
1
说明:按照shuxue成绩排名依次是 x i a o h u a f a n g f a n g m i n m i n xiaohua fangfang minminxiaohuafangfangminmin
样例2
输入
3 2
yuwen shuxue
fangfang 95 90
xiaohua 88 95
minmin 90 95
zongfen
1
2
3
4
5
6
输出
fangfang minmin xiaohua
1
说明:排序科目不存在,按总分排序 , f a n g f a n g fangfangfangfang 和 m i n m i n minminminmin 总分相同,按姓名的字典序顺序,f a n g f a n g fangfangfangfang 排在前面
二.解题思路
思路如下:
- 定义一个
Student
类,包含学生的姓名和每门课的成绩。 - 创建一个存储学生信息的数组,长度为10004,因为题目中给出学生数量不超过100。
- 定义一个要排序的课程名的下标变量
key_index
,初始值为0。 - 定义一个自定义的排序函数
student_comparator
,用于比较两个学生对象的成绩,首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。 - 读取输入,包括学生数量
n
、课程数量m
、课程名称数组、学生信息,以及要排序的课程名。 - 计算每个学生的总分,将总分添加到每个学生的成绩数组中。
- 寻找要排序的课程名在课程名称数组中的下标,若找不到,则将
key_index
赋值为最后一个位置,即总分所在的位置。 - 仅保留有效学生信息,即去掉未使用的数组空间。
- 使用自定义的排序函数对学生数组进行排序。
- 输出排序后的学生名字,按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。
三.题解代码
Python题解代码
class Student:
def __init__(self):
self.name = "" # 学生名字
self.scores = [] # 每门课成绩
students = [Student() for _ in range(10004)] # 存储学生信息的数组
key_index = 0 # 要排序的课程名的下标
# 自定义排序函数
def student_comparator(a, b):
if a.scores[key_index] != b.scores[key_index]:
return b.scores[key_index] - a.scores[key_index]
return (a.name > b.name) - (a.name < b.name)
n, m = map(int, input().split()) # 学生数量和课程数量
course_names = input().split() # 课程名数组
for i in range(1, n + 1):
student_info = input().split()
students[i].name = student_info[0] # 读取学生名字
total_score = 0
students[i].scores = list(map(int, student_info[1:])) # 读取每门课成绩
total_score = sum(students[i].scores) # 计算总分
students[i].scores.append(total_score) # 将总分放入成绩数组末尾
key = input() # 要排序的课程名
key_index = m # 若没找到,赋值为最后一个位置,也就是总分
for i in range(m): # 寻找这个课程名的下标
if course_names[i] == key:
key_index = i
break
students = students[1:n+1] # 仅保留有效学生信息
students.sort(key=lambda x: (x.scores[key_index], -ord(x.name[0])), reverse=True) # 排序
for i in range(n):
print(students[i].name, end=" ")
JAVA题解代码
import java.util.*;
class Main {
// 存储学生信息和成绩的结构体
static class Student {
String name; // 学生名字
List<Integer> scores; // 每门课成绩
}
static Student[] students = new Student[10004]; // 存储学生信息的数组
static int keyIndex; // 要排序的课程名的下标
// 自定义排序函数
static Comparator<Student> studentComparator = new Comparator<Student>() {
@Override
public int compare(Student a, Student b) {
if (!a.scores.get(keyIndex).equals(b.scores.get(keyIndex))) {
return b.scores.get(keyIndex) - a.scores.get(keyIndex);
}
return a.name.compareTo(b.name);
}
};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] courseNames = new String[1000]; // 课程名数组
int n, m; // 学生数量和课程数量
n = sc.nextInt();
m = sc.nextInt();
for (int i = 0; i < m; i++) {
courseNames[i] = sc.next(); // 读入课程名字
}
for (int i = 1; i <= n; i++) {
students[i] = new Student();
students[i].name = sc.next(); // 读取学生名字
int sum = 0;
students[i].scores = new ArrayList<>();
for (int j = 0; j < m; j++) {
int score = sc.nextInt();
students[i].scores.add(score); // 读取每门课成绩
sum += score;
}
students[i].scores.add(sum); // 将总分放入成绩数组末尾
}
String key = sc.next(); // 要排序的课程名
keyIndex = m; // 若没找到,赋值为最后一个位置,也就是总分
for (int i = 0; i < m; i++) { // 寻找这个课程名的下标
if (courseNames[i].equals(key)) {
keyIndex = i;
break;
}
}
Arrays.sort(students, 1, n + 1, studentComparator); // 排序
for (int i = 1; i <= n; i++) {
System.out.print(students[i].name);
if (i == n) System.out.println();
else System.out.print(" ");
}
}
}
C/C++题解代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 存储学生信息和成绩的结构体
struct Student {
string name; // 学生名字
vector<int> scores; // 每门课成绩
};
Student students[10004]; // 存储学生信息的数组
int keyIndex; // 要排序的课程名的下标
// 自定义排序函数
bool compare(Student &a, Student &b) {
if (a.scores[keyIndex] != b.scores[keyIndex]) // 如果分数不同,则先比较分数
return a.scores[keyIndex] > b.scores[keyIndex];
return a.name < b.name; // 反之比较学生名字
}
int main() {
string courseNames[1000]; // 课程名数组
int n, m; // 学生数量和课程数量
cin >> n >> m; // 读取学生数量和课程数量
for (int i = 0; i < m; i++) {
cin >> courseNames[i]; // 读入课程名字
}
for (int i = 1; i <= n; i++) {
cin >> students[i].name; // 读取学生名字
int sum = 0;
for (int j = 0; j < m; j++) {
int score;
cin >> score;
students[i].scores.push_back(score); // 读取每门课成绩
sum += score;
}
students[i].scores.push_back(sum); // 将总分放入成绩数组末尾
}
string key; // 要排序的课程名
cin >> key;
keyIndex = m; // 若没找到,赋值为最后一个位置,也就是总分
for (int i = 0; i < m; i++) { // 寻找这个课程名的下标
if (courseNames[i] == key) {
keyIndex = i;
break;
}
}
sort(students + 1, students + 1 + n, compare); // 排序
for (int i = 1; i <= n; i++) {
cout << students[i].name;
if (i == n) cout << endl;
else cout << " ";
}
return 0;
}
JS题解代码
const readline = require('readline');
class Student {
constructor(name, scores) {
this.name = name;
this.scores = scores;
}
// 自定义排序函数
static compare(a, b) {
if (a.scores[keyIndex] !== b.scores[keyIndex]) { // 如果分数不同,则先比较分数
return b.scores[keyIndex] - a.scores[keyIndex];
}
return a.name.localeCompare(b.name); // 反之比较学生名字
}
}
const students = new Array(10004); // 存储学生信息的数组
let keyIndex; // 要排序的课程名的下标
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let lineCount = 0;
let n, m;
let courseNames = new Array(1000); // 课程名数组
rl.on('line', (line) => {
if (lineCount === 0) {
[n, m] = line.split(' ').map(Number);
} else if (lineCount === 1) {
courseNames = line.split(' ');
} else {
const tokens = line.split(' ');
const name = tokens[0];
const scores = tokens.slice(1).map(Number);
const sum = scores.reduce((acc, cur) => acc + cur, 0);
scores.push(sum); // 将总分放入成绩数组末尾
students[lineCount - 1] = new Student(name, scores);
}
lineCount++;
if (lineCount > n + 1) {
const key = line.trim(); // 要排序的课程名
keyIndex = m; // 若没找到,赋值为最后一个位置,也就是总分
for (let i = 0; i < m; i++) { // 寻找这个课程名的下标
if (courseNames[i] === key) {
keyIndex = i;
break;
}
}
students.sort(Student.compare); // 排序
for (let i = 0; i < n; i++) {
process.stdout.write(students[i].name);
if (i === n - 1) console.log();
else process.stdout.write(' ');
}
process.exit(0); // 显式结束程序
}
});
代码OJ评判结果
通过测试点
四.代码讲解(Java&Python&C++&JS分别讲解)
Python题解代码解析:
-
定义
Student
类: 该类包含两个成员变量,分别是学生的名字(name
)和每门课的成绩(scores
)。 -
创建存储学生信息的数组:
students
是一个长度为10004的数组,用于存储学生信息。 -
初始化
key_index
:key_index
是要排序的课程名在科目数组中的下标,初始值为0。 -
自定义排序函数
student_comparator
: 该函数用于比较两个学生对象的成绩。首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。 -
读取输入: 从标准输入读取学生数量
n
和课程数量m
,以及科目名称数组course_names
。 -
读取学生信息: 使用循环读取每个学生的信息,包括学生姓名和每门课的成绩,计算总分,并将总分添加到成绩数组的末尾。
-
输入要排序的课程名
key
: 从标准输入读取要排序的课程名。 -
寻找要排序的课程名的下标
key_index
: 遍历科目名称数组,找到要排序的课程名在数组中的下标。 -
保留有效学生信息: 仅保留有效学生信息,去掉未使用的数组空间。
-
使用自定义排序函数对学生数组进行排序: 使用
sort
函数,按照指定的排序规则对学生数组进行排序。 -
输出排序后的学生名字: 遍历排序后的学生数组,按照题目要求输出学生的名字。
JAVA题解代码解析:
-
导入必要的包: 使用
import java.util.*;
导入 Java 中的相关包。 -
定义
Student
类: 该类与 Python 中的Student
类相似,包含学生的名字和每门课的成绩。 -
创建存储学生信息的数组:
students
是一个Student
类型的数组,用于存储学生信息。 -
初始化
keyIndex
:keyIndex
是要排序的课程名在科目数组中的下标,初始值为0。 -
定义自定义排序函数
studentComparator
: 该函数实现Comparator
接口,用于比较两个学生对象的成绩。首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。 -
读取输入: 使用
Scanner
从标准输入读取学生数量n
和课程数量m
,以及科目名称数组courseNames
。 -
读取学生信息: 使用循环读取每个学生的信息,包括学生姓名和每门课的成绩,计算总分,并将总分添加到成绩数组的末尾。
-
输入要排序的课程名
key
: 使用Scanner
从标准输入读取要排序的课程名。 -
寻找要排序的课程名的下标
keyIndex
: 遍历科目名称数组,找到要排序的课程名在数组中的下标。 -
排序: 使用
Arrays.sort
函数,按照指定的排序规则对学生数组进行排序。 -
输出排序后的学生名字: 遍历排序后的学生数组,按照题目要求输出学生的名字。
C/C++题解代码解析:
-
导入必要的头文件: 使用
#include <iostream>
和#include <vector>
导入 C++ 中的相关头文件。 -
定义
Student
结构体: 与前两种语言中的Student
类相似,包含学生的名字和每门课的成绩。 -
创建存储学生信息的数组:
students
是一个Student
类型的数组,用于存储学生信息。 -
初始化
keyIndex
:keyIndex
是要排序的课程名在科目数组中的下标,初始值为0。 -
定义自定义排序函数
compare
: 该函数用于比较两个学生对象的成绩。首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。 -
读取输入: 使用
cin
从标准输入读取学生数量n
和课程数量m
,以及科目名称数组courseNames
。 -
读取学生信息: 使用循环读取每个学生的信息,包括学生姓名和每门课的成绩,计算总分,并将总分添加到成绩数组的末尾。
-
输入要排序的课程名
key
: 使用cin
从标准输入读取要排序的课程名。 -
寻找要排序的课程名的下标
keyIndex
: 遍历科目名称数组,找到要排序的课程名在数组中的下标。 -
排序: 使用
std::sort
函数,按照指定的排序规则对学生数组进行排序。 -
输出排序后的学生名字: 遍历排序后的学生数组,按照题目要求输出学生的名字。
JS题解代码解析:
-
导入
readline
模块: 使用const readline = require('readline');
导入 Node.js 中的readline
模块。 -
定义
Student
类: 与前面的语言中的Student
类相似,包含学生的名字和每门课的成绩。 -
创建存储学生信息的数组:
students
是一个Student
类型的数组,用于存储学生信息。 -
初始化
keyIndex
:keyIndex
是要排序的课程名在科目数组中的下标,初始值为0。 -
定义自定义排序函数
compare
: 该函数用于比较两个学生对象的成绩。首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。 -
使用
readline
逐行读取输入: 使用readline
模块逐行读取输入,根据输入行数执行不同的操作。 -
读取输入: 读取学生数量
n
和课程数量m
,以及科目名称数组courseNames
。 -
读取学生信息: 使用循环读取每个学生的信息,包括学生姓名和每门课的成绩,计算总分,并将总分添加到成绩数组的末尾。
-
输入要排序的课程名
key
: 读取要排序的课程名。 -
寻找要排序的课程名的下标
keyIndex
: 遍历科目名称数组,找到要排序的课程名在数组中的下标。 -
排序: 使用
sort
函数,按照指定的排序规则对学生数组进行排序。 -
输出排序后的学生名字: 遍历排序后的学生数组,按照题目要求输出学生的名字。
寄语
🚀✨ 朋友,希望你的华为OD机试就像是一场轻松的技术party!愿你的代码如同畅快的音符,跳跃在键盘上,最后弹奏出一曲高分之歌。加油,你是技术舞台上的巨星!通过机试,就像是风轻云淡,轻轻松松就把高分收入囊中。祝愿你的编程之旅一路顺风,破风前行,每一行代码都是成功的注脚!🌈💻