2026华为OD面试题018:智能成绩表 题目描述小明来到某学校当老师需要将学生按考试总分或单科分数进行排名你能帮帮他吗输入描述第 1 行输入两个整数学生人数 n 和科目数量 m。0 n 1000 m 10。第 2 行输入 m 个科目名称彼此之间用空格隔开。科目名称只由英文字母构成单个长度不超过 10 个字符。科目的出现顺序和后续输入的学生成绩一一对应不会出现重复的科目名称。第 3 行开始的 n 行每行包含一个学生的姓名和该生 m 个科目的成绩空格隔开学生不会重名。学生姓名只由英文字母构成长度不超过 10 个字符。成绩是 0 到 100 的整数依次对应第 2 行中输入的科目。末尾一行输入用作排名的科目名称。若科目不存在则按总分进行排序。输出描述输出一行按成绩排序后的学生名字空格隔开。成绩相同时按姓名字典序升序排列。原题文件在输出描述成绩相处截断这里按常见题型补全为成绩相同时按姓名字典序升序排列。排序方向按常见排名习惯取降序分数高的在前。示例 1输入3 2 yuwen shuxue fangfang 95 90 xiaohong 88 95 xiaoxin 90 90 shuxue输出xiaohong fangfang xiaoxin示例 2科目不存在按总分排输入3 2 yuwen shuxue fangfang 95 90 xiaohong 88 95 xiaoxin 90 90 english输出fangfang xiaohong xiaoxin讲个故事班主任老李的排名难题老李刚接手三年级二班校长丢来一张成绩表让他排个名。按数学成绩排。校长撂下一句话就走了。老李一看fangfang 和 xiaoxin 数学都考了 90这谁排前面挠了半天头末尾按姓名拼音排fangfang 在 xiaoxin 前面搞定。结果第二天校长又改口按英语排。老李翻遍成绩表压根没有英语这科。那咋办按总分排呗。说白了这道题就是模拟老李的整个排榜过程指定科目就按科目排科目不存在就按总分排同分看名字。核心原理一次自定义排序整道题就一个核心动作排序。难点全在比较器上。比较器有两条规则按优先级从高到低按排名分数降序。分数高的排前面。分数相同时按姓名字典序升序。名字小的排前面。排名分数怎么定看末尾一行输入的科目名如果这科在科目表里排名分数就是该科成绩如果这科不存在排名分数就是总分所有科目之和所以关键是建一张科目名到科目下标的映射表查一下就知道按哪科排。查不到就退化为总分排序。拿示例 1 走一遍。按 shuxue 排三人数学成绩分别是 fangfang 90、xiaohong 95、xiaoxin 90。降序排xiaohong 95 分最高排第一。剩下两人都是 90按名字升序fangfang 在 xiaoxin 前面。最终输出xiaohong fangfang xiaoxin。换成示例 2english 这科不存在就按总分。三人总分 fangfang 185、xiaohong 183、xiaoxin 180降序就是fangfang xiaohong xiaoxin。怎么实现读入 n、m读入 m 个科目名建一张科目名到下标的映射读入 n 个学生每人存姓名、各科成绩顺手算出总分读入排名科目名查映射查到用对应科目成绩查不到用总分自定义排序分数降序同分按姓名升序输出排序后的姓名空格隔开代码实现C 语言#includestdio.h#includestdlib.h#includestring.htypedefstruct{charname[16];intscores[12];inttotal;}Student;Student stu[105];charsubjects[12][16];intrankIdx;// -1 表示按总分排否则是科目下标intcmp(constvoid*a,constvoid*b){Student*x(Student*)a;Student*y(Student*)b;intsx(rankIdx-1)?x-total:x-scores[rankIdx];intsy(rankIdx-1)?y-total:y-scores[rankIdx];if(sx!sy)returnsy-sx;// 分数降序returnstrcmp(x-name,y-name);// 姓名升序}intmain(){intn,m;scanf(%d %d,n,m);for(inti0;im;i)scanf(%s,subjects[i]);for(inti0;in;i){scanf(%s,stu[i].name);stu[i].total0;for(intj0;jm;j){scanf(%d,stu[i].scores[j]);stu[i].totalstu[i].scores[j];}}charrankSub[16];scanf(%s,rankSub);rankIdx-1;for(inti0;im;i){if(strcmp(rankSub,subjects[i])0){rankIdxi;break;}}qsort(stu,n,sizeof(Student),cmp);for(inti0;in;i){printf(%s%c,stu[i].name,in-1?\n: );}return0;}C#includebits/stdc.husingnamespacestd;structStudent{string name;vectorintscores;inttotal;};intmain(){intn,m;cinnm;vectorstringsubjects(m);mapstring,intsubIdx;for(inti0;im;i){cinsubjects[i];subIdx[subjects[i]]i;}vectorStudentstu(n);for(inti0;in;i){cinstu[i].name;stu[i].scores.resize(m);stu[i].total0;for(intj0;jm;j){cinstu[i].scores[j];stu[i].totalstu[i].scores[j];}}string rankSub;cinrankSub;intrankIdxsubIdx.count(rankSub)?subIdx[rankSub]:-1;sort(stu.begin(),stu.end(),[](constStudenta,constStudentb){intsa(rankIdx-1)?a.total:a.scores[rankIdx];intsb(rankIdx-1)?b.total:b.scores[rankIdx];if(sa!sb)returnsasb;// 分数降序returna.nameb.name;// 姓名升序});for(inti0;in;i){coutstu[i].name(in-1?\n: );}return0;}Javaimportjava.util.*;publicclassMain{publicstaticvoidmain(String[]args){ScannerscnewScanner(System.in);intnsc.nextInt();intmsc.nextInt();String[]subjectsnewString[m];MapString,IntegersubIdxnewHashMap();for(inti0;im;i){subjects[i]sc.next();subIdx.put(subjects[i],i);}String[]namesnewString[n];int[][]scoresnewint[n][m];int[]totalnewint[n];for(inti0;in;i){names[i]sc.next();for(intj0;jm;j){scores[i][j]sc.nextInt();total[i]scores[i][j];}}StringrankSubsc.next();IntegerhitsubIdx.get(rankSub);finalintidx(hitnull)?-1:hit;Integer[]ordernewInteger[n];for(inti0;in;i)order[i]i;Arrays.sort(order,(a,b)-{intsa(idx-1)?total[a]:scores[a][idx];intsb(idx-1)?total[b]:scores[b][idx];if(sa!sb)returnsb-sa;// 分数降序returnnames[a].compareTo(names[b]);// 姓名升序});StringBuildersbnewStringBuilder();for(inti0;in;i){if(i0)sb.append( );sb.append(names[order[i]]);}System.out.println(sb);}}JavaScriptconstreadlinerequire(readline);constrlreadline.createInterface({input:process.stdin});constlines[];rl.on(line,(line)lines.push(line.trim()));rl.on(close,(){const[n,m]lines[0].split(/\s/).map(Number);constsubjectslines[1].split(/\s/);constsubIdx{};subjects.forEach((s,i){subIdx[s]i;});conststudents[];for(leti0;in;i){constpartslines[2i].split(/\s/);constnameparts[0];constscoresparts.slice(1,1m).map(Number);consttotalscores.reduce((a,b)ab,0);students.push({name,scores,total});}constrankSublines[2n];constrankIdx(rankSubinsubIdx)?subIdx[rankSub]:-1;students.sort((a,b){constsa(rankIdx-1)?a.total:a.scores[rankIdx];constsb(rankIdx-1)?b.total:b.scores[rankIdx];if(sa!sb)returnsb-sa;// 分数降序returna.nameb.name?-1:(a.nameb.name?1:0);// 姓名升序});console.log(students.map(ss.name).join( ));});Pythonn,mmap(int,input().split())subjectsinput().split()sub_idx{s:ifori,sinenumerate(subjects)}students[]for_inrange(n):partsinput().split()nameparts[0]scoreslist(map(int,parts[1:1m]))students.append((name,scores,sum(scores)))rank_subinput().strip()rank_idxsub_idx.get(rank_sub,-1)defkey_fn(stu):name,scores,totalstu scoretotalifrank_idx-1elsescores[rank_idx]return(-score,name)# 分数取负实现降序姓名默认升序students.sort(keykey_fn)print( .join(s[0]forsinstudents))复杂度分析时间复杂度O(n * log n)主要是排序。读入和算总分是O(n * m)m 10 可视为常数空间复杂度O(n * m)存储所有学生成绩n 最大不到 100随便排。总结一下智能成绩表 自定义排序 科目映射查表。核心口诀排名科目查得到按单科排查不到按总分排分数降序同分按姓名升序建一张科目名到下标的映射是切换两种模式的关键这道题本身不难真正容易翻车的是同分处理忘了写姓名这一级比较器遇到同分用例就过不去。把比较器写全两条规则一个都不能少。你还在哪些排序题里栽过跟头欢迎在评论区聊聊。