Sort Students with a Comparator
Problem
Each input line has a name, an age and a score. Sort the students by score (highest first). If scores are equal, the younger student comes first. If age is also equal, sort by name in alphabetical order. Print the names, one per line.
Constraints
- 1 <= lines <= 10^5
Examples
Input
amit 20 90 bela 19 90 chen 21 85
Output
bela amit chen
Solutions
Sorting by several fields means comparing the first field, and only when it is equal comparing the next one. Compare numbers with Integer.compare, not by subtraction, because a - b can overflow for big values.
/*
* Problem : Process lines.
* Input : Several lines.
* Output : The names in order.
* Approach: Comparable or comparator.
* Time : O(n log n)
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: Student implements Comparable. compareTo defines the natural order: score high first, then age low first, then name.
static class Student implements Comparable<Student> {
final String name;
final int age;
final int score;
Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public int compareTo(Student other) {
if (score != other.score) {
return Integer.compare(other.score, score);
}
if (age != other.age) {
return Integer.compare(age, other.age);
}
return name.compareTo(other.name);
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
// Step 2: Put the students in a list and sort it. Collections.sort uses compareTo.
java.util.List<Student> students = new java.util.ArrayList<>();
for (String line : lines) {
String[] part = line.split(" ");
students.add(new Student(part[0], Integer.parseInt(part[1]), Integer.parseInt(part[2])));
}
java.util.Collections.sort(students);
// Step 3: Print the names in the new order.
String[] output = new String[students.size()];
for (int i = 0; i < output.length; i++) {
output[i] = students.get(i).name;
}
return output;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(String.join("\n", solve(lines)));
}
}
Hints (1)
- What do you compare when the scores are equal?