PAT-A 1039. Course List for Student (25)

一道STL(vector)的练习题。

题目链接在此

题意

有N名学生,K门课程,给出每门课程的选课学生。然后有N个查询,每个查询是某位学生的名字,要求输出每个查询的学生一共选了多少门课,以及每门课的编号。(当然输入、输出都是有限制的)

思路及实现

我想到的是两种思路:

第一种:
以课程为主体,将选择这门课的学生的名字加入到该门课程的学生列表中。

第二种:
以学生为主体,将该学生选择的课程的课程编号加入到该名学生的选课列表中。

在使用了第一种思路实现之后,最后一个点是超时的。因为数据量较大,只要用了string或者map的都会在最后一点测试点超时,并且在PAT上,大数据要尽量避免使用cin和cout进行输入输出。

下面是第一种思路的实现:

#include<stdio.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>

using namespace std;

//某课程注册的学生列表类 
struct courseReg{
    int courseNum;                 //课程编号
    vector< string > stuName; //学生姓名
    int stuNum;                   //注册该课程的学生数目

    courseReg(){
        stuNum = 0;         //初始化注册该课程的学生数为0 
    } 
};

int main(){

    int n,k;      //n:学生数目, k:课程数目 
    scanf("%d %d",&n, &k);

    courseReg cr[k];
    for(int i = 0; i < k; i++){
        int courseNum, stuNum;        //courseNum:课程号  stuName:学生数目 
        scanf("%d %d",&courseNum, &stuNum);

        cr[i].courseNum = courseNum;
        cr[i].stuNum = stuNum;

        string tempStuName;
        for(int j = 0; j < stuNum; j++){   //读入注册课程编号为courseNum的学生列表 
            cin >> tempStuName;
            cr[i].stuName.push_back(tempStuName);
        } 
    } 

    string query;       //查询的学生姓名 
    vector<int> print;  //输出的课程号数组 
    int count = 0;          //某学生已选课程的数量 
    for(int i = 0; i < n; i++){    //n个查询 
        cin >> query;
        for(int j = 0; j < k; j++){
            for(int m = 0; m < cr[j].stuNum; m++){
                if(cr[j].stuName[m] == query){
                    count++;
                    print.push_back(cr[j].courseNum);
                }
            }
        }

        sort(print.begin(), print.end());
        cout << query << " " << count;
        for(int index = 0; index < count; index++){
            cout << " ";
            cout << print[index];
        }
        cout << endl;

        count = 0; //置为count
        print.clear(); //清空print 
    }


    return 0;
} 

下面来看一下以学生为主体的实现:

#include<stdio.h>
#include<vector>
#include<algorithm>

using namespace std;

const int M = 26*26*26*10 + 1;


//学生姓名的映射
int getStuId(char name[]){
    int stuId = 0;
    for(int i = 0; i < 3; i++){
        stuId = stuId*26 + (name[i] - 'A');
    }
    stuId = stuId*10 + (name[3] - '0');

    return stuId;
} 

vector<int> courseList[M];   //学生选课列表 

int main(){

    int n,k;
    scanf("%d %d",&n, &k);   //学生总数,课程数量 

    int courseId, stuNum;   //课程编号, 学生数量 
    for(int i = 0; i < k; i++){
        scanf("%d %d", &courseId, &stuNum);
        char stuName[5];
        for(int j = 0; j < stuNum; j++){   //读取某课程选课学生姓名 
            scanf("%s",&stuName);
            int stuId = getStuId(stuName);
            courseList[stuId].push_back(courseId); 
        }
    }

    for(int i = 0; i < n; i++){  //读取查询,并输出结果 
        char stuName[5];
        scanf("%s", &stuName);
        int stuId = getStuId(stuName);
        sort(courseList[stuId].begin(), courseList[stuId].end());
        printf("%s ",stuName);
        printf("%d",courseList[stuId].size());
        for(int j = 0; j < courseList[stuId].size(); j++){
            printf(" %d", courseList[stuId][j]);
        }
        printf("\n");
    }

    return 0;
}

这种思想的实现主要是借助了 字符串hash 的处理方法(getStuId函数),对比上一种方法,降低了在比对查询的学生姓名时的时间复杂度。

关于字符串hash的问题,可以看这篇博客

除此之外,以上还有一个需要注意的地方:courseList数组需要开成全局,否则会内存超限,导致程序abort。


从这个题目的两种思路我们应该可以得出一个 结论:在程序中,应该以稍后需要查询的内容为主体(索引),以减少查询的时间复杂度。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值