返回目录

题目描述

小明来到某学校当老师,需要将学生按考试总分或单科分数进行排名,你能帮帮他吗?

输入描述

第 1 行输入两个整数,学生人数 n 和科目数量 m。

  • 0 < n < 100
  • 0 < m < 10

第 2 行输入 m 个科目名称,彼此之间用空格隔开。

  • 科目名称只由英文字母构成,单个长度不超过10个字符。
  • 科目的出现顺序和后续输入的学生成绩一一对应。
  • 不会出现重复的科目名称。

第 3 行开始的 n 行,每行包含一个学生的姓名和该生 m 个科目的成绩(空格隔开)

  • 学生不会重名。
  • 学生姓名只由英文字母构成,长度不超过10个字符。
  • 成绩是0\~100的整数,依次对应第2行种输入的科目。

第n+2行,输入用作排名的科目名称。若科目不存在,则按总分进行排序。

输出描述

输出一行,按成绩排序后的学生名字,空格隔开。成绩相同的按照学生姓名字典顺序排序。

示例

输 入3 2
yuwen shuxue
fangfang 95 90
xiaohua 88 95
minmin 100 82
shuxue
输 出xiaohua fangfang minmin
说 明按shuxue成绩排名,依次是xiaohua、fangfang、minmin
输入3 2
yuwen shuxue
fangfang 95 90
xiaohua 88 95
minmin 90 95
zongfen
输出fangfang minmin xiaohua
说明排序科目不存在,按总分排序,
fangfang和minmin总分相同,
按姓名的字典顺序,fangfang
排在前面

题目解析

本题是一道排序题。难度在于排序规则是动态的,不是固定的。

本题要求按照最后一行输入的科目的分数进行排序,如果对应科目不存在,则按照总分进行排序。

我的解题思路是:

首先,定义一个排名要素数组rank,分别记录各科成绩以及总分,即该排名要素数组rank的长度为 m + 1。

  • 第rank[0]\~rank[m-1]上,记录的是第二行输入科目顺序对应科目分数。
  • 第rank[m]上,记录的是所有科目的总分。

然后,定义一个有效要素索引(即最终用于指定规则的排序要素的索引),比如:

  • 最后一行输入了shuxue,那么我就去第二行输入:yuwen shuxue,中去找对应出现序号为 1,那么有效要素的索引就是1,最终用于制定排序规则的值就是 rank[1]。
  • 如果最后一行输入的科目,在第二行中不存在,那么就是按照总分制定排序规则,此时排序要素取 rank[m]。

如果排序要素值相同(可能是某科成绩,可能是总分),那么就再按照学生姓名的字典排序。

更多实现细节请看代码,已添加详细注释。

Python算法源码

# 定义学生类
class Student:
    def __init__(self, name):
        self.name = name
        self.rank = []

# 比较函数,用于排序学生
def compare(s1, s2):
    return s2.name < s1.name  # 按姓名降序排列

if __name__ == "__main__":
    n, m = map(int, input().split())  # 输入学生数和科目数

    # 输入科目名称并创建科目索引映射
    subjects = [input() for _ in range(m)]

    # 输入学生数据
    students = []
    for _ in range(n):
        name = input()  # 输入学生姓名
        ranks = list(map(int, input().split()))  # 输入学生各科目排名
        total_score = sum(ranks)  # 计算总分
        ranks.append(total_score)  # 将总分存入排名数组的最后一个元素
        student = Student(name)
        student.rank = ranks
        students.append(student)

    subject = input()  # 输入用于排名的科目

    rank_idx = m  # 默认为总分排名
    for i in range(m):
        if subject == subjects[i]:
            rank_idx = i
            break

    # 根据排名排序学生
    students.sort(key=lambda x: x.name, reverse=True)

    # 打印排序后的学生姓名
    for student in students:
        print(student.name, end=" ")

    # 释放动态分配的内存(Python不需要手动释放内存)

C算法源码

以下是对程序中各部分的中文注释:

include <stdio.h>

include <stdlib.h>

include <string.h>

// 定义学生结构体
typedef struct {

char name[100]; // 学生姓名
int *rank;      // 学生排名数组

} Student;

// 比较函数,用于排序学生
int compare(const void a, const void b) {

Student *s1 = (Student *)a;
Student *s2 = (Student *)b;
return strcmp(s2->name, s1->name); // 按姓名降序排列

}

int main() {

int n, m;
scanf("%d %d", &n, &m); // 输入学生数和科目数

// 输入科目名称并创建科目索引映射
char subjects[10][100];
int i, j;
for (i = 0; i < m; i++) {
    scanf("%s", subjects[i]);
}

// 创建学生数组
Student *students = (Student *)malloc(n * sizeof(Student));

// 输入学生数据
for (i = 0; i < n; i++) {
    scanf("%s", students[i].name); // 输入学生姓名
    students[i].rank = (int *)malloc((m + 1) * sizeof(int)); // 动态分配学生排名数组的内存
    for (j = 0; j < m; j++) {
        scanf("%d", &students[i].rank[j]); // 输入学生各科目排名
    }
    int totalScore = 0;
    for (j = 0; j < m; j++) {
        totalScore += students[i].rank[j]; // 计算总分
    }
    students[i].rank[m] = totalScore; // 将总分存入排名数组的最后一个元素
}

char subject[100];
scanf("%s", subject); // 输入用于排名的科目

int rankIdx = m; // 默认为总分排名
for (i = 0; i < m; i++) {
    if (strcmp(subject, subjects[i]) == 0) {
        rankIdx = i;
        break;
    }
}

// 根据排名排序学生
qsort(students, n, sizeof(Student), compare);

// 打印排序后的学生姓名
for (i = 0; i < n; i++) {
    printf("%s ", students[i].name);
}

// 释放动态分配的内存
for (i = 0; i < n; i++) {
    free(students[i].rank);
}
free(students);

return 0;

}


#### Java算法源码

import java.util.*;

class Student {

String name;
int[] rank;

public Student(String name, int[] rank) {
    this.name = name;
    this.rank = rank;
}

}

public class Main {

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    // 学生人数, 科目数量
    int n = scanner.nextInt();
    int m = scanner.nextInt();
    scanner.nextLine(); // Consume newline

    // key是科目名称,val是科目出现顺序的序号
    Map<String, Integer> subjectRankIdx = new HashMap<>();

    // 输入的m个科目
    String[] subjects = scanner.nextLine().split(" ");
    for (int i = 0; i < m; i++) {
        subjectRankIdx.put(subjects[i], i);
    }

    List<Student> students = new ArrayList<>();
    for (int i = 0; i < n; i++) {
        String[] tmp = scanner.nextLine().split(" ");

        // 学生姓名
        String name = tmp[0];
        // 学生给定科目的分数(m个)
        int[] scores = new int[m];
        for (int j = 0; j < m; j++) {
            scores[j] = Integer.parseInt(tmp[j + 1]);
        }

        // 排名要素,0~m-1索引上的是给定科目成绩,m索引上的是总分
        int[] rank = new int[m + 1];
        System.arraycopy(scores, 0, rank, 0, m);
        int totalScore = Arrays.stream(scores).sum();
        rank[m] = totalScore;

        students.add(new Student(name, rank));
    }

    // 用作排名的科目名称
    String subject = scanner.nextLine();

    // 用作排名的科目名称的排名要素序号, 如果用作排名的科目名称不存在,则按总分排名,对应序号是m
    int rankIdx = subjectRankIdx.getOrDefault(subject, m);

    // 按照排名要素排名,如果排名要素值相同,则按照学生姓名字典序排序
    Collections.sort(students, new Comparator<Student>() {
        @Override
        public int compare(Student s1, Student s2) {
            if (s1.rank[rankIdx] != s2.rank[rankIdx]) {
                return Integer.compare(s2.rank[rankIdx], s1.rank[rankIdx]);
            } else {
                return s1.name.compareTo(s2.name);
            }
        }
    });

    // Print sorted student names
    for (Student student : students) {
        System.out.print(student.name + " ");
    }
}

}

最后修改:2024 年 03 月 31 日
如果觉得我的文章对你有用,请随意赞赏