这道题也是典型的排序题目,但是对于拼题A给的时间限制,对Java选手不是很友好,因此,必须要优化输入操作,即快读操作,从而实现时间上的优势。
====================================================================
学生互评作业的简单规则是这样定的:每个人的作业会被k
个同学评审,得到k
个成绩。系统需要去掉一个最高分和一个最低分,将剩下的分数取平均,就得到这个学生的最后成绩。本题就要求你编写这个互评系统的算分模块。
输入格式:
输入第一行给出3个正整数N
(3 < N
≤104,学生总数)、k
(3 ≤ k
≤ 10,每份作业的评审数)、M
(≤ 20,需要输出的学生数)。随后N
行,每行给出一份作业得到的k
个评审成绩(在区间[0, 100]内),其间以空格分隔。
输出格式:
按非递减顺序输出最后得分最高的M
个成绩,保留小数点后3位。分数间有1个空格,行首尾不得有多余空格。
=====================================================================
通过分析题目,我们有两个思路,可以直接排序,但是排序数组长度为n,可能会耗时比较久,我们可以考虑用树状队列来进行优化,Java当中有一个很香的工具PriorityQueue可以实现优先队列,这里要求的是增序排序,如果题目要求降序,可以通过Comparator.comparing()函数进行要求排序。下面附上AC代码
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args)throws IOException{
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
int n = (int) in.nval;
in.nextToken();
int k = (int) in.nval;
in.nextToken();
int m = (int) in.nval;
PriorityQueue<Double> s = new PriorityQueue<>();//用来实现优先队列
for(int i = 0 ;i<n;i++){
double t=0;
int sum = 0, min = 100, max = 0;
for (int j = 0; j < k; j++) {
in.nextToken();
int x = (int) in.nval;
max = Math.max(max, x);
min = Math.min(min, x);
sum += x;
}
sum = sum - max - min;
t= (double) sum / (k - 2);
if(s.size()==m){ //只需存m个,因为m比较小所以运行速度很快
if(t>s.peek())s.poll(); //如果比最小情况小,就排除顶部再加新数
else continue;
}
s.add(t);
}
StringBuilder sb = new StringBuilder(); //用StringBuilder来优化输出
for (int i = n-m; i <n ; i++) {
sb.append(String.format("%.3f", s.poll()));
if (i < n - 1) sb.append(" ");
}
System.out.println(sb);
}
}
如果有什么可以再优化的地方,还请大佬们指出,感谢大家支持!