題目描述
您將會得到學生的資料清單,包含ID、名字和成績平均積點(CGPA)。您的任務是要依據成績平均積點遞減的方式重新排列學生的清單。若兩個學生擁有相同的成績平均積點,使用他們的名字的辭典順序來排列。如果學生的名字也相同,那麼就使用他們的ID來排列。
原題網址
輸入格式
第一行包含一個整數N,表示學生的數量,範圍在2到1000之間(包含2和1000)。接下來的N行為每個學生的ID、名字和成績平均積點,用空格隔開。ID的範圍在0到100000之間(包含0和100000),開頭不為0;名字的長度在5到30之間(包含5和30),使用小寫英文字母組成;成績平均積點在0到4.0之間(包含0和4.0),小數點最多有兩位。
輸出格式
重新排列學生的清單後,依序分行輸出學生的名字。
範例輸入
5
33 Rumpa 3.68
85 Ashis 3.85
56 Samiha 3.75
19 Samara 3.75
22 Fahim 3.76
33 Rumpa 3.68
85 Ashis 3.85
56 Samiha 3.75
19 Samara 3.75
22 Fahim 3.76
範例輸出
Ashis
Fahim
Samara
Samiha
Rumpa
Fahim
Samara
Samiha
Rumpa
解題概念
使用List物件的方法傳入Comparator參數來完成排序,Comparator的實作可以直接使用Lambda表示式來完成。首先判斷兩物件的成績平均積點,若前者大於後者,回傳-1;若前者小於後者,回傳1。如果成績平均積點相同,再來判斷兩物件的名字,由於名字是字串,所以可以直接使用字串物件的compareTo方法來比較其辭典順序,若小於0,回傳-1;若大於0,回傳1。如果辭典順序相等,要再判斷ID的順序,直接回傳前者ID減掉後者ID的結果即可。
參考答案
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Solution {
public static void main(final String[] args) {
final Scanner in = new Scanner(System.in);
int testCases = Integer.parseInt(in.nextLine());
final List<Student> studentList = new ArrayList<>();
while (testCases > 0) {
final int id = in.nextInt();
final String fname = in.next();
final double cgpa = in.nextDouble();
final Student st = new Student(id, fname, cgpa);
studentList.add(st);
testCases--;
}
studentList.sort((a, b) -> {
final double cgpaA = a.getCgpa(), cgpaB = b.getCgpa();
if (cgpaA > cgpaB) {
return -1;
} else if (cgpaA < cgpaB) {
return 1;
}
final int nameCompare = a.getFname().compareTo(b.getFname());
if (nameCompare < 0) {
return -1;
} else if (nameCompare > 0) {
return 1;
}
return a.getId() - b.getId();
});
for (final Student st : studentList) {
System.out.println(st.getFname());
}
}
}
class Student {
private int id;
private String fname;
private double cgpa;
public Student(final int id, final String fname, final double cgpa) {
super();
this.id = id;
this.fname = fname;
this.cgpa = cgpa;
}
public int getId() {
return id;
}
public String getFname() {
return fname;
}
public double getCgpa() {
return cgpa;
}
}