top1编程
← 返回题目
题解

倒数第一名

1 条题解

  • 0
    @ 2026-8-5 23:54:04

    P4620 倒数第一名(入门)

    解题思路

    这道题要找出英语成绩最低、而且并列时最先出现的那位同学。可以用"老师巡堂"的办法,分四步。

    第一步,把任务想清楚。 全班同学排成一列,老师从队首走到队尾,手里攥着一张"目前最差记录"。每走到一位同学,就看看他的成绩是不是比手里的记录还低:更低就把名字记下来;一样高或者更高就不换人。因为只有"更差"才换人,所以分数相同的后来者不会把先来者挤掉,最后留下的一定是"分数最低且最先出现"的同学。

    第二步,用一个例子验证思路。 前两位同学都考 60 分,老师记下第一位;第三位考 50 分,比 60 更差,换成第三位;第四位又考 50 分,和当前记录一样,不换。最后输出的就是第三位,也就是 50 分里最先出现的那位。注意全程只有一个"严格更低才更新",这是并列时保靠前者的关键。

    第三步,用结构体打包信息。 学号、姓名、成绩三样信息用结构体装在一起,整体赋值和比较都方便。姓名是字符串,用字符数组保存。

    第四步,注意初始值和输出格式。 成绩范围是 0 到 100,一开始把记录设成 101,这样无论第一位同学考多少分都比它低,保证第一次比较就能选中第一位同学。如果初始值设成 0,考 0 分的同学反而选不上,设成 101 更稳妥。最后输出学号和姓名,中间用空格隔开,记得换行。

    回顾总结。"找最差"和"找最好"其实是一对好兄弟,区别只在比较符号相反。用结构体保存当前最差记录,用"严格更差才更新"保证并列时保留先出现者,再把初始记录设成范围外的数 101,四步搞定。

    参考代码

    // 用途:找出英语成绩最低且最先出现的学生。
    #include <iostream>
    using namespace std;
    
    struct Student {
        int id;             // 学生的学号
        char name[101];     // 学生的姓名
        int score;          // 学生的英语成绩
    };
    
    int main() {
        int n;              // 学生人数
        cin >> n;           // 读入学生人数
    
        Student lastPlace;      // 保存目前倒数第一名的信息
        lastPlace.score = 101;  // 成绩最大为100,先放一个更大的数
    
        for (int i = 0; i < n; i++) {               // 依次读入每个学生
            Student current;                        // 当前学生的信息
            cin >> current.id >> current.name >> current.score;  // 读入学号、姓名和成绩
            if (current.score < lastPlace.score) {  // 当前成绩更低时更新答案
                lastPlace = current;                // 保存当前学生
            }
        }
    
        cout << lastPlace.id << ' ' << lastPlace.name << endl;  // 输出学号和姓名
        return 0;                                   // 程序结束
    }
    

    复杂度分析

    程序从头到尾把 n 个学生各读一遍、比较一遍,所以时间复杂度是 O(n)。这里 n 小于 1000,运行飞快,即使数据达到上限也只在一瞬间完成。程序只用了几个变量和一个结构体变量来保存"当前最差"的学生,额外空间是 O(1),不会随学生人数增长,无论 100 人还是 1000 人,用到的空间都一样少。

    • 1