Sorting nodes under two conditions? - java

only just started learning java and was stuck on this problem.
Let's say I have a list of employees (I'll use only three of this examples) in no particular order and I go through the list and create a sorted link of nodes that all contain a name and salary per week. These three nodes would individually look like so:
(John, 1000)
(Bob, 1000)
(Adam, 1000)
And I wanted to sort it first by salary then alphabetically by name so all the nodes connected would look something like this:
(Adam, 1000)(Bob, 1000)(John, 1000)
I also have a way of increase the salary so if I were to do something like bobNode.increaseBy(200) (the amount increased at a time will always be the same i.e 200 every time the method is called for every name) the connected nodes would update and look something like this
(Bob, 1200)(Adam, 1000)(John, 1000)
Is there any efficient or easy way to do this? Currently, I have a compareTo method in my Node class that returns this.name.compareTo(other.name) so the nodes are sorted alphabetically as I go through the list of employees. Is there anyway to check for both conditions and sort?
I was thinking about doing something like if salary.compareTo(other.salary) == 0 compare the names instead, but since the nodes would already exists in the linked list it wouldn't really work.
What about adding and sorting the nodes alphabetically first and whenever salary of a node is adjusted removing that node and adding it again to the correct position?
Another idea I had that's similar to the previous was to remove the adjusted nodes and creating a new linked list of nodes that contains all the nodes with that amount of salary sorted alphabetically. I will then add these new nodes after I have gone through the list of employees. Wouldn't this be a bit problematic if say I had a list of 200,000 employees with a wide range of salary thus I would have to create and iterate through many nodes?
I also wanted to note that the salary can increase without having all the employees be added first.
Any help and ideas would be greatly appreciated!

Related

what is right algorithm and data structure for a user defined collection with specific insertion and deletion

This question is asked in one of investment banking company's interview .
I have to design myCache which keeps a cache of studentRecords object and can have one object of myCache of studentRecords collection.When user wants to insert record in studentRecords it will only insert record if there is less than 20 record in collection .otherwise it will remove the least used record from the studentRecords and insert the record.Record will be inserted on basis of ranking of studentRecords in sorted order.When user wants to read the record it will check if studentRecords exist in myCache ,if not exist then will read record from studentRecords collection.
I created a doubly linked list and insert the record on basis of ranking .also can make a mycache class which is singleton and reads records from cache .But how to delete records which are least used .
I can create a array list which delete records top in array(least used record) but can not keep elements on basis of ordering of rank. and to read record on basis of ranking is expensive again .
Is there any other solution which would have impressed interviewer.
myCache class have functions like :
public void removeRecordFromStudentRecords(String rank);
public void addRecordToStudentRecords(StudentRecords st);
public Student readRecordFromStudentRecords(String rank);
table of StudentRecords
SrNo rank name maths science total percentage
1 1 rohan 90 90 180 90
2 2 sohan 80 90 160 80
3 3 abhi 70 70 140 70
If we're talking about a Cache we should optimize time complexity first and memory later.
So, in this case, I can provide next solution:
Use Map (i.e. HashMap) for storing records (key: recordId, value: Record).
Use Stack for last used items (value: recordId).
Use Tree (i.e. BST) for holding rank (key: rankValue, value: recordId).
Combination of this tree data structures allows to provide the fastest solution (I guess).
Read by Id operation: O(1) - just simple get from the map
Add record operation: O(ln N) - because we need to insert key into tree (we do not include balancing into counting complaxity)
Remove by rank operation: O(ln N) - simply finding recordId by rank in Tree( don't forget removing record from Map and recordID from Stack)
This is just brief overview of the problem. Guess, it's enough info to understand the main idea.
In order to keep a track of the least used record, you need to store the number of hits each record has (if you do not know what "hits" are, I suggest you look up "hits and misses in caching") So each studentRecord can be an object of a class as follows:
class StudentRecord{
int unique_id;
int ranking;
int hits
}
StudentRecord studentRecord = new StudentRecord();
sort your cache based on studentRecord.ranking and when you need to decide which studentRecord to delete, simply traverse the cache on the basis of hits and delete the element with the minimum hits.
To maintain hits, whenever you get a query for a studentRecord based on its unique_id, you increment its hits by 1. Thus, hits will give you a metric of which studentRecord is most used/least used
EDIT: Your question is now much clearer. For sorting, you can use simple insertion sort. The reasons for this are 1) you have max 20 elements in your cache and 2) when you try and insert a new element, insertion sort will help you perfectly to find the index where you can place the element. In fact, technically speaking, you need only sort once. Then you just need to figure out where to insert future elements.
I would say a simple linked list with arbitrary access (like java.util.ArrayList) will suffice. It will give you random access as in arrays and also the provision to accomodate less than 20 elements. I see no reason to make a doubly linked list since there is no need to access an element's left and right neighbours here...
Least Recently Used Scheduling technique can be applied here,you can keep a byte field for each entry in your list.
So everytime an entry of your object is used you can push 1 to the byte(b>>1).
So for entries which are being more frequently used, you'll have a lot of 1s in the binary representation for your byte.
For data, not being used at all will have all 0s.
And everytime, you are required to delete an entry from your cache, just delete the one with 0 or the one with the smallest value of this byte field.
Also, to remember references for greater time spans than just eight, you can use bigger datatypes.

What data structure to choose for an ELO rating system with 20k+ entries?

I have some Objects (currently 20 000 +) that have the following Attributes
Object
----------
String name
int rating
I want to create an ELO rating for all these Objects. This implies the following:
To adjust the ELO of 2 Objects matched against each other I need to find those Objects in the list by name.
To Display the List I need to get every Object ordered by its rating.
The whole program will be implemented in Java, but I think its independent from the programming language.
Currently I am unsure which data model to choose for this Project. A friend advised me to use a 2-4 tree to insert the Objects ordered by name so I can change the rating of each object fast.
However the Objects are printed in order of their rating rather than by name and I don't want to sort so many Objects every time I output the list.
As I am pretty new to data structures: What is the usual way to solve this problem?
Creating another tree ordered by rating?
Having a list of ratings and each rating linked to each Object currently having that rating?
Edit: ELO rating is a mapping from the set of objects to the integers. Each object only gets one rating but a rating can have multiple Objects associated with it.
Creating another tree ordered by rating? Having a list of ratings and each rating linked to each Object currently having that rating?
Well , this is one way to do so , but will take huge space also since you have 20K+ entries .
The best way i can think of now is :
Use datastructure like multimap with key=name , and value = ratings.
This way , everytime you insert a new object in multimap , it will take O(logN) time .
To find all ratings with same name use equal_range , which is also an O(logN) operation .
Hope this helps !
A HashMap with name as the key will give you O(1) performance when matching the elements, keep a TreeSet with a rating Comparator and you'll have the items in order. Although you'll need to reinsert an element if the rating changes.

Efficient way to get elements out of a treeset with different sorting criteria

I have a treeset containing student objects(name, roll number, address and age) and are stored in ascending order of their names and if the names are same, then roll numbers. This list is coming from a file and could get really big.
Now i have to provide a way to display the list that could be in any order - sorted in ascending/descending order according to name, age, address or roll number. I am looking for an efficient solution for my problem.
What i am thinking of doing is to take a temporary arraylist and get the elements into it in the order i want. But for this i will have to implement a different method for every criteria and this looks inefficient to me.
Is there any way i can get the elements in the treeset out in the way i want into an array coz i just need to print the values and destroy the temp list afterwards
The only way to do it is, as you said, iterating over the tree and pulling out all of the matching elements into an ArrayList. Once you've done that you can sort based on a particular Comparator.
If you just want to pull out elements based on the natural ordering, you can use the subset method, but that depends on the compareTo method in the tree, which is not valid for all the different searches that you want to do.
Given that, why are you using a TreeSet in the first place? Do your elements have a natural ordering that the TreeSet leverages? If not why not just dump them all into an ArrayList and sort the ArrayList as necessary?

ConcurrentSkipListMap sorting: Can it be done by the value's compareTo?

In a game, I'm trying to keep a list of users and have it sorted by score, so that I could query the list at any given time and return (for example) the top ten users by score. This list should be thread-safe. I envision using the userName string as a key and the value would be a User object which implements Comparable and has properties such as displayName and score. The User object would therefore have a compareTo method which would compare the score attribute to determine its position.
I'm looking at using a ConcurrentSkipListMap for this, but as best I can tell, the Map (as opposed to the Set) uses the key to sort. I'd like to have the list sorted by the score property of the User object, but still use a Map because I need to be able access any given user and modify their score attribute from a thread.
It doesn't seem that using my own Comparator for the key would solve my problem, as I doubt I'd have access to the associated value for comparison. I could use a ConcurrentSkipListSet but accessing the list to modify an individual user's score would be (I would imagine) an expensive operation (due to the need to iterate every time).
Would anyone be able to suggest how to accomplish this?
No, I don't think you can. The comparator used for ordering is the same one used for indexing. You will probably have to maintain 2 collections. One for keeping the ordering of user's scores the for referring to the users by name.
get(key) depends on the comparator (to be able to locate the key). You propose a comparator that would depend on get(key) (to access the mapped value of a key an compare based on that). That necessarily leads to infinite recursion and stack overflow (on the bright side, you are posting at the right website!!)
Michael is right, you can't have your cake and eat it too ;)
I think you have 3 choices:
Use a Map so that updates to a user's score are quick, and you pay the price when sorting to find the highest scores.
Use a SortedSet that sorts by score so that finding the highest scores is fast, but you must pay the price when updating user's scores
Maintain two data structures, so that you can have the best of 1 and 2. For example, you have your real data in a set sorted by score, but then also maintain a mapping of username to index into the set or similar. That way you always have the sorted scores, and updating a user's score is just a lookup, not a search. The price you pay for this is now you are maintaining some duplicate information in two places, and especially considering concurrent access, it can be tricky ensuring both places are always updated in synch.
I would not make assumptions about which is faster between 1 & 2. I would try them both out with your expected usage and measure to see what is worst.
If you are really only interested in the top n scores, then there is the possibility to just maintain that list separately. So have your map of username to score for everyone, but also maintain a small set of the top scores (and their users). Every time you add/update someone's score, just check the score against the top score list, and if it's bigger than the smallest one there, just add it and bump off the lower one. This is similar to suggestion 3 above, but is less overhead and perhaps easier to maintain.

Find top ten values in a Map

Say I have a TreeMap<String, Treeset<Song>>, where object Song has three String fields and an internal CompareTo method. The keys for the map are unique words in the lyrics that are not common words such as "she", "the", "if", or "on". There are multiple copies of Songs in the map, since there are an average of 60 words mapped to a single Song.
For extra credit, the professor asked us to come up with an algorithm to find the top 10 values in the map. I didn't solve the problem in time, which is why I'm asking here.
The part that I'm stumped on is, unlike with an ordered array or list, you can't just grab the top values sequentially. So, I thought about:
Create a PriorityQueue<Node> with the Comparator sorting the Nodes based
on the Set size
iterate over the map
for each map node
create a Node object with the key-value pair
insert Node into the queue
Even though the PriorityQueue will end up with all the key-value pairs, the top sizes will be at the top, and I can just retrieve the first ten.
This seems like a very roundabout way, since this particular map has 31,000+ nodes mapping to over 637,000 values. Is there a better way?
A simple modification of your algorithm:
Create a PriorityQueue<Node> with the Comparator sorting the Nodes based
on the Set size
iterate over the map
for each map node
if value for node is larger than last entry in priority queue
create a Node object with the key-value pair
insert Node into the queue
trim the queue to ten entries
At completion, the priority queue will only contain the top 10 entries.
I am not sure you want the top 10 by key, in which case Soldier.moth is right and you can specifically obtain a descending view calling descendingMap and then iterate for the first 10 elements. But if you want the top 10 by some other relation, just iterate over the elementSet and store the current top 10 in a sorted data structure, like TreeSet specifying a comparator based on size -- not sure what size you mean but you probably know -- and for every element you replace the smallest of the 10 if it is smaller than the current. You obtain the smallest with firstKey

Categories