Sort students by marks in Java

 


Problem:

The problem statement requires sorting an array "roll[]" according to the values of another array "marks[]". In other words, the values in "roll[]" array must be arranged in the same order as the values in "marks[]" array when it is sorted in decreasing order.

For instance, given the inputs roll[] = {101, 108, 103, 105} and marks[] = {70, 80, 40, 90}, the expected output is {105, 108, 101, 103} since when we sort marks[] in decreasing order, we get {90, 80, 70, 40}, and the values in roll[] corresponding to these marks are 105, 108, 101, and 103, respectively.

Solution:

To solve this problem, we can use a class to represent a group of elements where the first element is from the "marks[]" array and the second element is from the "roll[]" array corresponding to the same index as the chosen "marks[]" array element. We can then create an ArrayList of these classes for all N items in both arrays.

After creating the ArrayList, we can sort it in decreasing order according to the first value in the group of pairs, which is the marks[] value. Finally, we can traverse the ArrayList and print all second values of pair, which are now arranged according to the increasing order of marks values.

Here is an implementation of the above solution in Java:

java
import java.util.*; class Student{ int rollno; int marks; Student(int r, int m) { rollno = r; marks = m; } } class MyCmp implements Comparator<Student> { public int compare(Student s1, Student s2) { return s2.marks - s1.marks; } } class Solution { static void printByMarks(int roll[], int marks[]) { int n = roll.length; List<Student> al = new ArrayList<Student>(n); for(int i=0; i<n; i++) { al.add(new Student(roll[i], marks[i])); } Collections.sort(al, new MyCmp()); for(Student x : al) { System.out.print(x.rollno + " "); } } public static void main(String args[]) { int roll[] = {101, 108, 103, 105}; int marks[] = {70, 80, 40, 90}; printByMarks(roll, marks); } }

In the implementation above, we first define a class "Student" that has two attributes: "rollno" and "marks". We use this class to represent a group of elements, where the first element is a marks[] value, and the second element is the corresponding roll[] value.

We then define a custom comparator "MyCmp" to sort the list of Student objects in decreasing order according to the marks[] attribute.

In the "printByMarks" method, we create an ArrayList of Student objects, where each object represents a group of marks[] and roll[] values. We then sort this ArrayList using the "MyCmp" comparator.

Finally, we traverse the sorted ArrayList and print the roll[] values in the order of increasing marks[] values.

In the main method, we create the input arrays "roll[]" and "marks[]" and call the "printByMarks" method to get the sorted roll[] values.

The output of the program with input roll[] = {101, 108, 103, 105} and marks[] = {70, 80, 40, 90} is {105, 108, 101, 103} which is the expected output. Similarly, for the input roll[] = {103, 105, 101} and marks[] = {70, 80, 40}, the expected output is {105, 103, 101}.

The solution provided above uses a custom class called "Student" to represent a group of two values, where the first value is the marks obtained by a student and the second value is the roll number of that student. The class has two instance variables, rollno and marks, which are assigned values using a parameterized constructor.

The solution also uses a custom comparator called "MyCmp" to sort the list of "Student" objects. The comparator compares two "Student" objects based on their "marks" instance variables in descending order.

The "printByMarks" method creates an ArrayList of "Student" objects and adds N such objects, where N is the length of the input arrays. Then, it sorts the ArrayList using the custom comparator "MyCmp" and prints the sorted roll numbers in the order they appear in the sorted ArrayList.

Overall, the solution is efficient and easy to understand. However, there are some improvements that could be made to make the code more concise and readable.

Firstly, instead of creating a custom class "Student", we can use the built-in class "Map.Entry" to represent the pairs of marks and roll numbers. The Map.Entry interface provides a convenient way to represent a pair of key-value pairs, where the key is the marks obtained by a student and the value is the roll number of that student.

Secondly, instead of creating a separate comparator class "MyCmp", we can use a lambda expression to define the comparator function. A lambda expression is a concise way to define an anonymous function that can be used as a comparator.

With these improvements, the updated solution looks like this:

java
import java.util.*; class GfG { static void printByMarks(int roll[], int marks[]) { int n = roll.length; List<Map.Entry<Integer, Integer>> list = new ArrayList<>(); for (int i = 0; i < n; i++) { list.add(new AbstractMap.SimpleEntry<>(marks[i], roll[i])); } Collections.sort(list, (a, b) -> b.getKey() - a.getKey()); for (Map.Entry<Integer, Integer> entry : list) { System.out.println(entry.getValue()); } } public static void main(String args[]) { int roll[] = {101, 108, 103, 105}; int marks[] = {70, 80, 40, 90}; printByMarks(roll, marks); } }

In this updated solution, we first create a list of Map.Entry objects by iterating over the input arrays and adding new entries to the list. The AbstractMap.SimpleEntry class is used to create new entries, where the first parameter is the key (marks) and the second parameter is the value (roll number).

Then, we sort the list using a lambda expression that compares the entries based on their keys in descending order.

Finally, we print the roll numbers in the order they appear in the sorted list using a for-each loop over the entries.

Overall, the updated solution is more concise and easier to read, while still achieving the same result as the original solution.

Previous Post Next Post