Bootstrap

智能成绩表【华为OD机试】(JAVA&Python&C++&JS题解)

一. 题目-智能成绩表

小明来到学校当老师,需要将学生按考试总分或单科分数进行排名,你能帮帮他吗?
输入描述
第 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 排在前面

二.解题思路

思路如下:

  1. 定义一个Student类,包含学生的姓名和每门课的成绩。
  2. 创建一个存储学生信息的数组,长度为10004,因为题目中给出学生数量不超过100。
  3. 定义一个要排序的课程名的下标变量key_index,初始值为0。
  4. 定义一个自定义的排序函数student_comparator,用于比较两个学生对象的成绩,首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。
  5. 读取输入,包括学生数量n、课程数量m、课程名称数组、学生信息,以及要排序的课程名。
  6. 计算每个学生的总分,将总分添加到每个学生的成绩数组中。
  7. 寻找要排序的课程名在课程名称数组中的下标,若找不到,则将key_index赋值为最后一个位置,即总分所在的位置。
  8. 仅保留有效学生信息,即去掉未使用的数组空间。
  9. 使用自定义的排序函数对学生数组进行排序。
  10. 输出排序后的学生名字,按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。

三.题解代码

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题解代码解析:

  1. 定义Student类: 该类包含两个成员变量,分别是学生的名字(name)和每门课的成绩(scores)。

  2. 创建存储学生信息的数组: students 是一个长度为10004的数组,用于存储学生信息。

  3. 初始化key_index key_index 是要排序的课程名在科目数组中的下标,初始值为0。

  4. 自定义排序函数student_comparator 该函数用于比较两个学生对象的成绩。首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。

  5. 读取输入: 从标准输入读取学生数量 n 和课程数量 m,以及科目名称数组 course_names

  6. 读取学生信息: 使用循环读取每个学生的信息,包括学生姓名和每门课的成绩,计算总分,并将总分添加到成绩数组的末尾。

  7. 输入要排序的课程名 key 从标准输入读取要排序的课程名。

  8. 寻找要排序的课程名的下标 key_index 遍历科目名称数组,找到要排序的课程名在数组中的下标。

  9. 保留有效学生信息: 仅保留有效学生信息,去掉未使用的数组空间。

  10. 使用自定义排序函数对学生数组进行排序: 使用 sort 函数,按照指定的排序规则对学生数组进行排序。

  11. 输出排序后的学生名字: 遍历排序后的学生数组,按照题目要求输出学生的名字。

JAVA题解代码解析:

  1. 导入必要的包: 使用 import java.util.*; 导入 Java 中的相关包。

  2. 定义 Student 类: 该类与 Python 中的 Student 类相似,包含学生的名字和每门课的成绩。

  3. 创建存储学生信息的数组: students 是一个 Student 类型的数组,用于存储学生信息。

  4. 初始化 keyIndex keyIndex 是要排序的课程名在科目数组中的下标,初始值为0。

  5. 定义自定义排序函数 studentComparator 该函数实现 Comparator 接口,用于比较两个学生对象的成绩。首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。

  6. 读取输入: 使用 Scanner 从标准输入读取学生数量 n 和课程数量 m,以及科目名称数组 courseNames

  7. 读取学生信息: 使用循环读取每个学生的信息,包括学生姓名和每门课的成绩,计算总分,并将总分添加到成绩数组的末尾。

  8. 输入要排序的课程名 key 使用 Scanner 从标准输入读取要排序的课程名。

  9. 寻找要排序的课程名的下标 keyIndex 遍历科目名称数组,找到要排序的课程名在数组中的下标。

  10. 排序: 使用 Arrays.sort 函数,按照指定的排序规则对学生数组进行排序。

  11. 输出排序后的学生名字: 遍历排序后的学生数组,按照题目要求输出学生的名字。

C/C++题解代码解析:

  1. 导入必要的头文件: 使用 #include <iostream>#include <vector> 导入 C++ 中的相关头文件。

  2. 定义 Student 结构体: 与前两种语言中的 Student 类相似,包含学生的名字和每门课的成绩。

  3. 创建存储学生信息的数组: students 是一个 Student 类型的数组,用于存储学生信息。

  4. 初始化 keyIndex keyIndex 是要排序的课程名在科目数组中的下标,初始值为0。

  5. 定义自定义排序函数 compare 该函数用于比较两个学生对象的成绩。首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。

  6. 读取输入: 使用 cin 从标准输入读取学生数量 n 和课程数量 m,以及科目名称数组 courseNames

  7. 读取学生信息: 使用循环读取每个学生的信息,包括学生姓名和每门课的成绩,计算总分,并将总分添加到成绩数组的末尾。

  8. 输入要排序的课程名 key 使用 cin 从标准输入读取要排序的课程名。

  9. 寻找要排序的课程名的下标 keyIndex 遍历科目名称数组,找到要排序的课程名在数组中的下标。

  10. 排序: 使用 std::sort 函数,按照指定的排序规则对学生数组进行排序。

  11. 输出排序后的学生名字: 遍历排序后的学生数组,按照题目要求输出学生的名字。

JS题解代码解析:

  1. 导入 readline 模块: 使用 const readline = require('readline'); 导入 Node.js 中的 readline 模块。

  2. 定义 Student 类: 与前面的语言中的 Student 类相似,包含学生的名字和每门课的成绩。

  3. 创建存储学生信息的数组: students 是一个 Student 类型的数组,用于存储学生信息。

  4. 初始化 keyIndex keyIndex 是要排序的课程名在科目数组中的下标,初始值为0。

  5. 定义自定义排序函数 compare 该函数用于比较两个学生对象的成绩。首先按照要排序的课程成绩降序排列,如果成绩相同则按学生姓名的字典顺序升序排列。

  6. 使用 readline 逐行读取输入: 使用 readline 模块逐行读取输入,根据输入行数执行不同的操作。

  7. 读取输入: 读取学生数量 n 和课程数量 m,以及科目名称数组 courseNames

  8. 读取学生信息: 使用循环读取每个学生的信息,包括学生姓名和每门课的成绩,计算总分,并将总分添加到成绩数组的末尾。

  9. 输入要排序的课程名 key 读取要排序的课程名。

  10. 寻找要排序的课程名的下标 keyIndex 遍历科目名称数组,找到要排序的课程名在数组中的下标。

  11. 排序: 使用 sort 函数,按照指定的排序规则对学生数组进行排序。

  12. 输出排序后的学生名字: 遍历排序后的学生数组,按照题目要求输出学生的名字。

寄语

🚀✨ 朋友,希望你的华为OD机试就像是一场轻松的技术party!愿你的代码如同畅快的音符,跳跃在键盘上,最后弹奏出一曲高分之歌。加油,你是技术舞台上的巨星!通过机试,就像是风轻云淡,轻轻松松就把高分收入囊中。祝愿你的编程之旅一路顺风,破风前行,每一行代码都是成功的注脚!🌈💻

在这里插入图片描述

;