I have the following information of students with corresponding marks and ranks
Name Marks Rank
A 30 1
B 20 2
C 10 3
The rank of the student is inversely proportional to the marks of the student. I have to find the best data structure to store the above information so that the following operations are executed in the most optimal manner(Best time complexity) . It can be assumed that student name is unique.
I am thinking of using two hashmaps one for student and marks mapping and another for student name and rank mapping. Is there a better data structure for this?. Is there a way that i can make use of the fact that rank is inversely proportional to marks.
'struct' keyword is used to create the student structure as: struct Student { char* name; int roll_number; int age; double total_marks; };
This can be done with two data structures: A hash map that maps from student name to his grade. An order statistic tree of students, where the key for comparisons is the grade.
The number of items is extremely large. Dynamic linked list is a good solution.
Best is probably a bucketed hash table. By placing hash collisions into buckets and keeping separate arrays in the bucket for keys and values, you can both reduce the size of the table proper and take advantage of CPU cache speedup when searching a bucket.
This can be done with two data structures:
This allows you to do all of the following operations in O(logn)
:
In addition, Finding a student's grade is done in O(1)
(average case) using the hash map alone.
Note:
You can switch implementation of the student name->grade map to a tree map rather than hash map without influencing the complexity too much, and guaranteeing better worst case behavior. (Finding a grade will also be O(logn) and not O(1) with this change).
My suggestion is also to use two HashMap
, but one of them is filled gradually instead of adding it's sorting complexity to update time. This would provide the following properties:
byStudent
reorder
out of the addOrUpdate
method, updating in batches, and calling reorder after each batch from the outside.byRank
reading.class MyClass {
Comparator<RankedStudent> comp = Comparator.comparingInt(e -> e.marks);
private Map<String, RankedStudent> repo = new HashMap<>();
private Map<Integer, RankedStudent> rankCache = new HashMap<>();
public RankedStudent getByStudent(String student) {
return repo.get(student);
}
public RankedStudent getByRank(Integer rank) {
return Optional.ofNullable(rankCache.get(rank)).orElseGet(() -> {
rankCache.putIfAbsent(rank, repo.values().stream().sorted((s1, s2) -> rank == s1.rank ? 1 : 0)
.findFirst().orElse(null));
return rankCache.get(rank);
});
}
public void addOrUpdate(String student, Integer marks) {
repo.put(student, new RankedStudent(student, marks, -1));
reorder();
}
public void reorder() {
final Iterator<RankedStudent> it = repo.values().stream().sorted(comp.reversed()).iterator();
IntStream.range(0, repo.size()).boxed().forEach(i -> it.next().rank = i + 1);
rankCache.clear();
}
}
class RankedStudent {
public String name;
public int marks;
public int rank;
public RankedStudent(String name, int marks, int rank) {
this.name = name;
this.marks = marks;
this.rank = rank;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With