Ranking Score SystemRanking and sorting on Array/ListClean, efficient and extensible code for querying...
Why is searching for a value in an object by key slower than using 'for in' in js?
Is it true that real estate prices mainly go up?
Can anyone tell me why this program fails?
Do I need life insurance if I can cover my own funeral costs?
An Accountant Seeks the Help of a Mathematician
How to make readers know that my work has used a hidden constraint?
Professor being mistaken for a grad student
Be in awe of my brilliance!
How to simplify this time periods definition interface?
Checking if rendered lightning:input components are populated
Prove that this set in the metric space is open
It's a yearly task, alright
/bin/ls output does not match manpage
How do I hide Chekhov's Gun?
If Invisibility ends because the original caster casts a non-concentration spell, does Invisibility also end on other targets of the original casting?
No, nay, never, no more
What is a good source for large tables on the properties of water?
What is IP squat space
What is Thermal Runaway Protection?
Brexit - No Deal Rejection
Does splitting a potentially monolithic application into several smaller ones help prevent bugs?
Why do passenger jet manufacturers design their planes with stall prevention systems?
What to do when during a meeting client's people start to (physically) fight with each other?
Running a subshell from the middle of the current command
Ranking Score System
Ranking and sorting on Array/ListClean, efficient and extensible code for querying collectionsCalculate final test score from a list of test resultsSimple object oriented design of student systemStudents with second lowest gradeMaximizing grad student happinessHackerank - value of friendshipHackerrank: Kindergarten AdventuresA semaphore implmentation with Peterson's N process algorithmMr. Muffin's ball-passing game
$begingroup$
I have an assignment to solve this problem. There are a total of 12 test case files, 1 of which that I have failed due to exceeding limit on the script.
Question Description
Bob has somehow managed to obtain a class list of $N$ students that
contains the name of the students, as well as their scores for an
exam. The task is to generate the rank of each student in the class
list.
Let $S$ be the number of students in the class list that have
obtained a higher score than student $X$. The rank of student
$X$ in the class list is formally defined as $(S+1)$. This means that if there are many students that obtain the same score, they will
all have the same rank.
Input
The first line of input contains a single integer $N$, the number of
students in the class list.
$N$ lines will follow. Each line will describe one student in the following form: [name] [score].
Output
For each student, print the rank of the student in the following form:
[name] [rank]. These students should be printed in the same order as
the input.
Limits
$1 leq N leq 50000
All the names of students will only contain uppercase and lowercase
English letters with no spaces. The names will not be more than 20
characters long. It is possible that there can be 2 students with the
same name.
All scores of students will range from 0 to 109 inclusive.
Does anyone have a solution to my problem? Do inform me if any more information is needed. Any other comments on coding styles and space complexities that may arise are also appreciated, though the focus should be the time.
Here's my code and test cases.
import java.util.*;
//Comparator to rank people by score in ascending order
//No tiebreaking for equal scores is considered in this question
class PairComparator implements Comparator<List<Object>> {
public int compare(List<Object> o1, List<Object> o2) {
return (Integer)o1.get(0) - (Integer)o2.get(0);
}
}
public class Ranking {
private void run() {
Scanner sc = new Scanner(System.in);
ArrayList<List<Object>> inputPairs = new ArrayList<>();
ArrayList<String> nameIterList = new ArrayList<>();//To store names in scanned order
HashMap<String, Integer> dupeCount = new HashMap<>();//To consider cases where there are people with same names
int count = sc.nextInt();
for (int i=0;i<count;i++) {
String name = sc.next();
int score = sc.nextInt();
name = checkDuplicates(nameIterList,name,dupeCount);//returns a unique name after considering duplicates
List<Object> pair = List.of(score,name);//simulates a struct data structure in C with non-homogeneous elements
inputPairs.add(pair);
nameIterList.add(name);
}
Collections.sort(inputPairs, (new PairComparator()).reversed());//descending order sorting
HashMap<String,Integer> nameRank = new HashMap<>();//name and respective rank in O(1) time
makeTable(nameRank,inputPairs);
for (String name: nameIterList) {
System.out.println(String.format("%s %d",name.trim(),nameRank.get(name)));
} //for displaying purposes, repeated name is printed
}
public static void main(String[] args) {
Ranking newRanking = new Ranking();
newRanking.run();
}
public static void makeTable(HashMap<String,Integer> nameRank, ArrayList<List<Object>> inputPairs) {
int lowestRank = 1;
int previousScore = (Integer)inputPairs.get(0).get(0);
for (int i=0;i<inputPairs.size();i++) {
List<Object> pairs = inputPairs.get(i);
String name = (String) pairs.get(1);
int score = (Integer) pairs.get(0);
int currentRank = i+1;//default rank if there are no tiebreakers
if (score==previousScore) {
currentRank = lowestRank;//takes the smallest possible rank for a tie-breaker
} else {
lowestRank = currentRank;//updates the smallest possible rank as tie-breaker is broken
previousScore = score;
}
nameRank.put(name,currentRank);//updates HashMap
}
}
public static String checkDuplicates(ArrayList<String> nameList, String name, HashMap<String,Integer> dupeCount) {
if (dupeCount.containsKey(name)) {
int count = dupeCount.get(name);
dupeCount.replace(name,count+1); //updates the duplicateTable
return name+ new String(new char[count]).replace('', ' ');//new name is appending with spaces, trimmed later on
} else {//entry not found, add in as the first one
dupeCount.put(name,1);
return name;//no change
}
}
}
Sample Inputs
25
Sloane 15
RartheCat 94
Taylor 34
Shark 52
Jayce 58
Westin 91
Blakely 6
Dexter 1
Davion 78
Saanvi 65
Tyson 15
Kiana 31
Roberto 88
Shark 55
MrPanda 25
Rar 26
Blair 12
RartheCat 81
Zip 74
Saul 58
ProfTan 77
SJShark 0
Georgia 79
Darian 44
Aleah 7
Sample Output
Sloane 19
RartheCat 1
Taylor 15
Shark 13
Jayce 10
Westin 2
Blakely 23
Dexter 24
Davion 6
Saanvi 9
Tyson 19
Kiana 16
Roberto 3
Shark 12
MrPanda 18
Rar 17
Blair 21
RartheCat 4
Zip 8
Saul 10
ProfTan 7
SJShark 25
Georgia 5
Darian 14
Aleah 22
java algorithm programming-challenge time-limit-exceeded
$endgroup$
add a comment |
$begingroup$
I have an assignment to solve this problem. There are a total of 12 test case files, 1 of which that I have failed due to exceeding limit on the script.
Question Description
Bob has somehow managed to obtain a class list of $N$ students that
contains the name of the students, as well as their scores for an
exam. The task is to generate the rank of each student in the class
list.
Let $S$ be the number of students in the class list that have
obtained a higher score than student $X$. The rank of student
$X$ in the class list is formally defined as $(S+1)$. This means that if there are many students that obtain the same score, they will
all have the same rank.
Input
The first line of input contains a single integer $N$, the number of
students in the class list.
$N$ lines will follow. Each line will describe one student in the following form: [name] [score].
Output
For each student, print the rank of the student in the following form:
[name] [rank]. These students should be printed in the same order as
the input.
Limits
$1 leq N leq 50000
All the names of students will only contain uppercase and lowercase
English letters with no spaces. The names will not be more than 20
characters long. It is possible that there can be 2 students with the
same name.
All scores of students will range from 0 to 109 inclusive.
Does anyone have a solution to my problem? Do inform me if any more information is needed. Any other comments on coding styles and space complexities that may arise are also appreciated, though the focus should be the time.
Here's my code and test cases.
import java.util.*;
//Comparator to rank people by score in ascending order
//No tiebreaking for equal scores is considered in this question
class PairComparator implements Comparator<List<Object>> {
public int compare(List<Object> o1, List<Object> o2) {
return (Integer)o1.get(0) - (Integer)o2.get(0);
}
}
public class Ranking {
private void run() {
Scanner sc = new Scanner(System.in);
ArrayList<List<Object>> inputPairs = new ArrayList<>();
ArrayList<String> nameIterList = new ArrayList<>();//To store names in scanned order
HashMap<String, Integer> dupeCount = new HashMap<>();//To consider cases where there are people with same names
int count = sc.nextInt();
for (int i=0;i<count;i++) {
String name = sc.next();
int score = sc.nextInt();
name = checkDuplicates(nameIterList,name,dupeCount);//returns a unique name after considering duplicates
List<Object> pair = List.of(score,name);//simulates a struct data structure in C with non-homogeneous elements
inputPairs.add(pair);
nameIterList.add(name);
}
Collections.sort(inputPairs, (new PairComparator()).reversed());//descending order sorting
HashMap<String,Integer> nameRank = new HashMap<>();//name and respective rank in O(1) time
makeTable(nameRank,inputPairs);
for (String name: nameIterList) {
System.out.println(String.format("%s %d",name.trim(),nameRank.get(name)));
} //for displaying purposes, repeated name is printed
}
public static void main(String[] args) {
Ranking newRanking = new Ranking();
newRanking.run();
}
public static void makeTable(HashMap<String,Integer> nameRank, ArrayList<List<Object>> inputPairs) {
int lowestRank = 1;
int previousScore = (Integer)inputPairs.get(0).get(0);
for (int i=0;i<inputPairs.size();i++) {
List<Object> pairs = inputPairs.get(i);
String name = (String) pairs.get(1);
int score = (Integer) pairs.get(0);
int currentRank = i+1;//default rank if there are no tiebreakers
if (score==previousScore) {
currentRank = lowestRank;//takes the smallest possible rank for a tie-breaker
} else {
lowestRank = currentRank;//updates the smallest possible rank as tie-breaker is broken
previousScore = score;
}
nameRank.put(name,currentRank);//updates HashMap
}
}
public static String checkDuplicates(ArrayList<String> nameList, String name, HashMap<String,Integer> dupeCount) {
if (dupeCount.containsKey(name)) {
int count = dupeCount.get(name);
dupeCount.replace(name,count+1); //updates the duplicateTable
return name+ new String(new char[count]).replace('', ' ');//new name is appending with spaces, trimmed later on
} else {//entry not found, add in as the first one
dupeCount.put(name,1);
return name;//no change
}
}
}
Sample Inputs
25
Sloane 15
RartheCat 94
Taylor 34
Shark 52
Jayce 58
Westin 91
Blakely 6
Dexter 1
Davion 78
Saanvi 65
Tyson 15
Kiana 31
Roberto 88
Shark 55
MrPanda 25
Rar 26
Blair 12
RartheCat 81
Zip 74
Saul 58
ProfTan 77
SJShark 0
Georgia 79
Darian 44
Aleah 7
Sample Output
Sloane 19
RartheCat 1
Taylor 15
Shark 13
Jayce 10
Westin 2
Blakely 23
Dexter 24
Davion 6
Saanvi 9
Tyson 19
Kiana 16
Roberto 3
Shark 12
MrPanda 18
Rar 17
Blair 21
RartheCat 4
Zip 8
Saul 10
ProfTan 7
SJShark 25
Georgia 5
Darian 14
Aleah 22
java algorithm programming-challenge time-limit-exceeded
$endgroup$
add a comment |
$begingroup$
I have an assignment to solve this problem. There are a total of 12 test case files, 1 of which that I have failed due to exceeding limit on the script.
Question Description
Bob has somehow managed to obtain a class list of $N$ students that
contains the name of the students, as well as their scores for an
exam. The task is to generate the rank of each student in the class
list.
Let $S$ be the number of students in the class list that have
obtained a higher score than student $X$. The rank of student
$X$ in the class list is formally defined as $(S+1)$. This means that if there are many students that obtain the same score, they will
all have the same rank.
Input
The first line of input contains a single integer $N$, the number of
students in the class list.
$N$ lines will follow. Each line will describe one student in the following form: [name] [score].
Output
For each student, print the rank of the student in the following form:
[name] [rank]. These students should be printed in the same order as
the input.
Limits
$1 leq N leq 50000
All the names of students will only contain uppercase and lowercase
English letters with no spaces. The names will not be more than 20
characters long. It is possible that there can be 2 students with the
same name.
All scores of students will range from 0 to 109 inclusive.
Does anyone have a solution to my problem? Do inform me if any more information is needed. Any other comments on coding styles and space complexities that may arise are also appreciated, though the focus should be the time.
Here's my code and test cases.
import java.util.*;
//Comparator to rank people by score in ascending order
//No tiebreaking for equal scores is considered in this question
class PairComparator implements Comparator<List<Object>> {
public int compare(List<Object> o1, List<Object> o2) {
return (Integer)o1.get(0) - (Integer)o2.get(0);
}
}
public class Ranking {
private void run() {
Scanner sc = new Scanner(System.in);
ArrayList<List<Object>> inputPairs = new ArrayList<>();
ArrayList<String> nameIterList = new ArrayList<>();//To store names in scanned order
HashMap<String, Integer> dupeCount = new HashMap<>();//To consider cases where there are people with same names
int count = sc.nextInt();
for (int i=0;i<count;i++) {
String name = sc.next();
int score = sc.nextInt();
name = checkDuplicates(nameIterList,name,dupeCount);//returns a unique name after considering duplicates
List<Object> pair = List.of(score,name);//simulates a struct data structure in C with non-homogeneous elements
inputPairs.add(pair);
nameIterList.add(name);
}
Collections.sort(inputPairs, (new PairComparator()).reversed());//descending order sorting
HashMap<String,Integer> nameRank = new HashMap<>();//name and respective rank in O(1) time
makeTable(nameRank,inputPairs);
for (String name: nameIterList) {
System.out.println(String.format("%s %d",name.trim(),nameRank.get(name)));
} //for displaying purposes, repeated name is printed
}
public static void main(String[] args) {
Ranking newRanking = new Ranking();
newRanking.run();
}
public static void makeTable(HashMap<String,Integer> nameRank, ArrayList<List<Object>> inputPairs) {
int lowestRank = 1;
int previousScore = (Integer)inputPairs.get(0).get(0);
for (int i=0;i<inputPairs.size();i++) {
List<Object> pairs = inputPairs.get(i);
String name = (String) pairs.get(1);
int score = (Integer) pairs.get(0);
int currentRank = i+1;//default rank if there are no tiebreakers
if (score==previousScore) {
currentRank = lowestRank;//takes the smallest possible rank for a tie-breaker
} else {
lowestRank = currentRank;//updates the smallest possible rank as tie-breaker is broken
previousScore = score;
}
nameRank.put(name,currentRank);//updates HashMap
}
}
public static String checkDuplicates(ArrayList<String> nameList, String name, HashMap<String,Integer> dupeCount) {
if (dupeCount.containsKey(name)) {
int count = dupeCount.get(name);
dupeCount.replace(name,count+1); //updates the duplicateTable
return name+ new String(new char[count]).replace('', ' ');//new name is appending with spaces, trimmed later on
} else {//entry not found, add in as the first one
dupeCount.put(name,1);
return name;//no change
}
}
}
Sample Inputs
25
Sloane 15
RartheCat 94
Taylor 34
Shark 52
Jayce 58
Westin 91
Blakely 6
Dexter 1
Davion 78
Saanvi 65
Tyson 15
Kiana 31
Roberto 88
Shark 55
MrPanda 25
Rar 26
Blair 12
RartheCat 81
Zip 74
Saul 58
ProfTan 77
SJShark 0
Georgia 79
Darian 44
Aleah 7
Sample Output
Sloane 19
RartheCat 1
Taylor 15
Shark 13
Jayce 10
Westin 2
Blakely 23
Dexter 24
Davion 6
Saanvi 9
Tyson 19
Kiana 16
Roberto 3
Shark 12
MrPanda 18
Rar 17
Blair 21
RartheCat 4
Zip 8
Saul 10
ProfTan 7
SJShark 25
Georgia 5
Darian 14
Aleah 22
java algorithm programming-challenge time-limit-exceeded
$endgroup$
I have an assignment to solve this problem. There are a total of 12 test case files, 1 of which that I have failed due to exceeding limit on the script.
Question Description
Bob has somehow managed to obtain a class list of $N$ students that
contains the name of the students, as well as their scores for an
exam. The task is to generate the rank of each student in the class
list.
Let $S$ be the number of students in the class list that have
obtained a higher score than student $X$. The rank of student
$X$ in the class list is formally defined as $(S+1)$. This means that if there are many students that obtain the same score, they will
all have the same rank.
Input
The first line of input contains a single integer $N$, the number of
students in the class list.
$N$ lines will follow. Each line will describe one student in the following form: [name] [score].
Output
For each student, print the rank of the student in the following form:
[name] [rank]. These students should be printed in the same order as
the input.
Limits
$1 leq N leq 50000
All the names of students will only contain uppercase and lowercase
English letters with no spaces. The names will not be more than 20
characters long. It is possible that there can be 2 students with the
same name.
All scores of students will range from 0 to 109 inclusive.
Does anyone have a solution to my problem? Do inform me if any more information is needed. Any other comments on coding styles and space complexities that may arise are also appreciated, though the focus should be the time.
Here's my code and test cases.
import java.util.*;
//Comparator to rank people by score in ascending order
//No tiebreaking for equal scores is considered in this question
class PairComparator implements Comparator<List<Object>> {
public int compare(List<Object> o1, List<Object> o2) {
return (Integer)o1.get(0) - (Integer)o2.get(0);
}
}
public class Ranking {
private void run() {
Scanner sc = new Scanner(System.in);
ArrayList<List<Object>> inputPairs = new ArrayList<>();
ArrayList<String> nameIterList = new ArrayList<>();//To store names in scanned order
HashMap<String, Integer> dupeCount = new HashMap<>();//To consider cases where there are people with same names
int count = sc.nextInt();
for (int i=0;i<count;i++) {
String name = sc.next();
int score = sc.nextInt();
name = checkDuplicates(nameIterList,name,dupeCount);//returns a unique name after considering duplicates
List<Object> pair = List.of(score,name);//simulates a struct data structure in C with non-homogeneous elements
inputPairs.add(pair);
nameIterList.add(name);
}
Collections.sort(inputPairs, (new PairComparator()).reversed());//descending order sorting
HashMap<String,Integer> nameRank = new HashMap<>();//name and respective rank in O(1) time
makeTable(nameRank,inputPairs);
for (String name: nameIterList) {
System.out.println(String.format("%s %d",name.trim(),nameRank.get(name)));
} //for displaying purposes, repeated name is printed
}
public static void main(String[] args) {
Ranking newRanking = new Ranking();
newRanking.run();
}
public static void makeTable(HashMap<String,Integer> nameRank, ArrayList<List<Object>> inputPairs) {
int lowestRank = 1;
int previousScore = (Integer)inputPairs.get(0).get(0);
for (int i=0;i<inputPairs.size();i++) {
List<Object> pairs = inputPairs.get(i);
String name = (String) pairs.get(1);
int score = (Integer) pairs.get(0);
int currentRank = i+1;//default rank if there are no tiebreakers
if (score==previousScore) {
currentRank = lowestRank;//takes the smallest possible rank for a tie-breaker
} else {
lowestRank = currentRank;//updates the smallest possible rank as tie-breaker is broken
previousScore = score;
}
nameRank.put(name,currentRank);//updates HashMap
}
}
public static String checkDuplicates(ArrayList<String> nameList, String name, HashMap<String,Integer> dupeCount) {
if (dupeCount.containsKey(name)) {
int count = dupeCount.get(name);
dupeCount.replace(name,count+1); //updates the duplicateTable
return name+ new String(new char[count]).replace('', ' ');//new name is appending with spaces, trimmed later on
} else {//entry not found, add in as the first one
dupeCount.put(name,1);
return name;//no change
}
}
}
Sample Inputs
25
Sloane 15
RartheCat 94
Taylor 34
Shark 52
Jayce 58
Westin 91
Blakely 6
Dexter 1
Davion 78
Saanvi 65
Tyson 15
Kiana 31
Roberto 88
Shark 55
MrPanda 25
Rar 26
Blair 12
RartheCat 81
Zip 74
Saul 58
ProfTan 77
SJShark 0
Georgia 79
Darian 44
Aleah 7
Sample Output
Sloane 19
RartheCat 1
Taylor 15
Shark 13
Jayce 10
Westin 2
Blakely 23
Dexter 24
Davion 6
Saanvi 9
Tyson 19
Kiana 16
Roberto 3
Shark 12
MrPanda 18
Rar 17
Blair 21
RartheCat 4
Zip 8
Saul 10
ProfTan 7
SJShark 25
Georgia 5
Darian 14
Aleah 22
java algorithm programming-challenge time-limit-exceeded
java algorithm programming-challenge time-limit-exceeded
edited 20 mins ago
Vogel612♦
21.8k447130
21.8k447130
asked 15 hours ago
Prashin JeevaganthPrashin Jeevaganth
1755
1755
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
$begingroup$
Your data model is slowing down your code.
ArrayList<List<Object>> inputPairs = new ArrayList<>();
ArrayList<String> nameIterList = new ArrayList<>();//To store names in scanned order
HashMap<String, Integer> dupeCount = new HashMap<>();//To consider cases where there are people with same names
Calling ArrayList.add()
will add an item to the array list. If insufficient room exists in its storage area, the area reallocated double its previous size, and the information copied to the new storage area. With 50000 names, with an initial allocated space of 8 items, you will go through 13 reallocations of the inputPairs
and nameIterList
containers.
The HashMap
stores its information differently, but it will suffer from the same doubling of capacity steps, with an additional penalty of "rebinning" the contents into the proper bins.
All of this takes time, and all of this can all be avoided by pre-allocating your storage container sizes. You know what the limit is: 50000. Alternately, you can read in N
and then allocate properly sized storage containers.
int count = sc.nextInt();
ArrayList<List<Object>> inputPairs = new ArrayList<>(count);
ArrayList<String> nameIterList = new ArrayList<>(count);
HashMap<String, Integer> dupeCount = new HashMap<>(count*2);
A HashMap
will rebin by default at 75% capacity, so I've initialized it at double the required capacity, so it won't exceed the limit.
ArrayList<List<Object>>
may not be the worst storage structure to use, but it comes close. List.of(score,name)
should allocate a specialized, immutable two-member structure to use for the list, but you still have to go through the overhead of the List
interface to .get()
at the members. Worst, the score
has to be boxed from an efficient int
into a full blown Integer
object. This auto boxing takes both time and space. Worse, the additional object allocations will cause additional cache misses, slowing down the program. True, the Integer
objects will probably all be interned varieties, due to their restricted range, but it all adds up to your time-limit-exceeded issue.
List.of(score, name)
was used to avoid creating your own simple class:
class StudentRecord {
String name;
int score;
}
Instead of 3 objects (at least) per student, you only have two: the StudentRecord
and the name
. Access to the member fields is fast; no .get(int)
overhead. (But even this is overhead that you don't need!)
Checking for duplicate names, and creating fake names to avoid the duplicates is a time wasting operation. We can avoid it, with a smarter algorithm.
The better way
First: let's simplify the data down to the bare minimum...
int count = sc.nextInt();
String[] names = new String[count];
int[] score = new int[count];
... two parallel arrays, one containing the student names (in order), and one containing the scores (in order).
Let's jump to the middle...
int[] rank = new int[110];
You have 110 possible score values, each which corresponds to exactly one rank. If you have 5 students with a score of 109 and one student with a score of 108, then rank[109]
should contain 1
, and rank[108]
should contain 6
.
Jumping to the end...
for(int i=0; i<count; i++) {
System.out.printf("%s %dn", name[i], rank[score[i]]);
}
... prints out the student, looks up the rank corresponding to their score and prints that as well.
Creation of the rank[]
array
Since this is a programming challenge, I'll leave this up to you. There are several ways to do it. Good luck.
$endgroup$
$begingroup$
Hi, I like your ideas. Unfortunately, I have a small typo in my question that might cause a huge change to the solution. The range is 10^9 instead of 109, so I think the rank[] array now has to become a HashMap to handle a SparseMatrix representation.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
For this scenario caused by the typo, I do think your scenario can work. In particular, using an array to store names did better than using an encryption mechanism to make unique names, I imparted your idea to the real problem and modified accordingly and it works. I will accept your answer here for someone who meets with similar problems.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
That’s a pretty big small typo. :-) Make sure you pre-allocate the required capacity in your sparse matrixHashMap
for maximum efficiency.
$endgroup$
– AJNeufeld
5 hours ago
$begingroup$
Hmm, even in the previous implementation which has exceeded time limit, increasing the capacity still fails. My current implementation can pass the time limit even without allocating capacity, but thanks for the reminder
$endgroup$
– Prashin Jeevaganth
4 hours ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215393%2franking-score-system%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Your data model is slowing down your code.
ArrayList<List<Object>> inputPairs = new ArrayList<>();
ArrayList<String> nameIterList = new ArrayList<>();//To store names in scanned order
HashMap<String, Integer> dupeCount = new HashMap<>();//To consider cases where there are people with same names
Calling ArrayList.add()
will add an item to the array list. If insufficient room exists in its storage area, the area reallocated double its previous size, and the information copied to the new storage area. With 50000 names, with an initial allocated space of 8 items, you will go through 13 reallocations of the inputPairs
and nameIterList
containers.
The HashMap
stores its information differently, but it will suffer from the same doubling of capacity steps, with an additional penalty of "rebinning" the contents into the proper bins.
All of this takes time, and all of this can all be avoided by pre-allocating your storage container sizes. You know what the limit is: 50000. Alternately, you can read in N
and then allocate properly sized storage containers.
int count = sc.nextInt();
ArrayList<List<Object>> inputPairs = new ArrayList<>(count);
ArrayList<String> nameIterList = new ArrayList<>(count);
HashMap<String, Integer> dupeCount = new HashMap<>(count*2);
A HashMap
will rebin by default at 75% capacity, so I've initialized it at double the required capacity, so it won't exceed the limit.
ArrayList<List<Object>>
may not be the worst storage structure to use, but it comes close. List.of(score,name)
should allocate a specialized, immutable two-member structure to use for the list, but you still have to go through the overhead of the List
interface to .get()
at the members. Worst, the score
has to be boxed from an efficient int
into a full blown Integer
object. This auto boxing takes both time and space. Worse, the additional object allocations will cause additional cache misses, slowing down the program. True, the Integer
objects will probably all be interned varieties, due to their restricted range, but it all adds up to your time-limit-exceeded issue.
List.of(score, name)
was used to avoid creating your own simple class:
class StudentRecord {
String name;
int score;
}
Instead of 3 objects (at least) per student, you only have two: the StudentRecord
and the name
. Access to the member fields is fast; no .get(int)
overhead. (But even this is overhead that you don't need!)
Checking for duplicate names, and creating fake names to avoid the duplicates is a time wasting operation. We can avoid it, with a smarter algorithm.
The better way
First: let's simplify the data down to the bare minimum...
int count = sc.nextInt();
String[] names = new String[count];
int[] score = new int[count];
... two parallel arrays, one containing the student names (in order), and one containing the scores (in order).
Let's jump to the middle...
int[] rank = new int[110];
You have 110 possible score values, each which corresponds to exactly one rank. If you have 5 students with a score of 109 and one student with a score of 108, then rank[109]
should contain 1
, and rank[108]
should contain 6
.
Jumping to the end...
for(int i=0; i<count; i++) {
System.out.printf("%s %dn", name[i], rank[score[i]]);
}
... prints out the student, looks up the rank corresponding to their score and prints that as well.
Creation of the rank[]
array
Since this is a programming challenge, I'll leave this up to you. There are several ways to do it. Good luck.
$endgroup$
$begingroup$
Hi, I like your ideas. Unfortunately, I have a small typo in my question that might cause a huge change to the solution. The range is 10^9 instead of 109, so I think the rank[] array now has to become a HashMap to handle a SparseMatrix representation.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
For this scenario caused by the typo, I do think your scenario can work. In particular, using an array to store names did better than using an encryption mechanism to make unique names, I imparted your idea to the real problem and modified accordingly and it works. I will accept your answer here for someone who meets with similar problems.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
That’s a pretty big small typo. :-) Make sure you pre-allocate the required capacity in your sparse matrixHashMap
for maximum efficiency.
$endgroup$
– AJNeufeld
5 hours ago
$begingroup$
Hmm, even in the previous implementation which has exceeded time limit, increasing the capacity still fails. My current implementation can pass the time limit even without allocating capacity, but thanks for the reminder
$endgroup$
– Prashin Jeevaganth
4 hours ago
add a comment |
$begingroup$
Your data model is slowing down your code.
ArrayList<List<Object>> inputPairs = new ArrayList<>();
ArrayList<String> nameIterList = new ArrayList<>();//To store names in scanned order
HashMap<String, Integer> dupeCount = new HashMap<>();//To consider cases where there are people with same names
Calling ArrayList.add()
will add an item to the array list. If insufficient room exists in its storage area, the area reallocated double its previous size, and the information copied to the new storage area. With 50000 names, with an initial allocated space of 8 items, you will go through 13 reallocations of the inputPairs
and nameIterList
containers.
The HashMap
stores its information differently, but it will suffer from the same doubling of capacity steps, with an additional penalty of "rebinning" the contents into the proper bins.
All of this takes time, and all of this can all be avoided by pre-allocating your storage container sizes. You know what the limit is: 50000. Alternately, you can read in N
and then allocate properly sized storage containers.
int count = sc.nextInt();
ArrayList<List<Object>> inputPairs = new ArrayList<>(count);
ArrayList<String> nameIterList = new ArrayList<>(count);
HashMap<String, Integer> dupeCount = new HashMap<>(count*2);
A HashMap
will rebin by default at 75% capacity, so I've initialized it at double the required capacity, so it won't exceed the limit.
ArrayList<List<Object>>
may not be the worst storage structure to use, but it comes close. List.of(score,name)
should allocate a specialized, immutable two-member structure to use for the list, but you still have to go through the overhead of the List
interface to .get()
at the members. Worst, the score
has to be boxed from an efficient int
into a full blown Integer
object. This auto boxing takes both time and space. Worse, the additional object allocations will cause additional cache misses, slowing down the program. True, the Integer
objects will probably all be interned varieties, due to their restricted range, but it all adds up to your time-limit-exceeded issue.
List.of(score, name)
was used to avoid creating your own simple class:
class StudentRecord {
String name;
int score;
}
Instead of 3 objects (at least) per student, you only have two: the StudentRecord
and the name
. Access to the member fields is fast; no .get(int)
overhead. (But even this is overhead that you don't need!)
Checking for duplicate names, and creating fake names to avoid the duplicates is a time wasting operation. We can avoid it, with a smarter algorithm.
The better way
First: let's simplify the data down to the bare minimum...
int count = sc.nextInt();
String[] names = new String[count];
int[] score = new int[count];
... two parallel arrays, one containing the student names (in order), and one containing the scores (in order).
Let's jump to the middle...
int[] rank = new int[110];
You have 110 possible score values, each which corresponds to exactly one rank. If you have 5 students with a score of 109 and one student with a score of 108, then rank[109]
should contain 1
, and rank[108]
should contain 6
.
Jumping to the end...
for(int i=0; i<count; i++) {
System.out.printf("%s %dn", name[i], rank[score[i]]);
}
... prints out the student, looks up the rank corresponding to their score and prints that as well.
Creation of the rank[]
array
Since this is a programming challenge, I'll leave this up to you. There are several ways to do it. Good luck.
$endgroup$
$begingroup$
Hi, I like your ideas. Unfortunately, I have a small typo in my question that might cause a huge change to the solution. The range is 10^9 instead of 109, so I think the rank[] array now has to become a HashMap to handle a SparseMatrix representation.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
For this scenario caused by the typo, I do think your scenario can work. In particular, using an array to store names did better than using an encryption mechanism to make unique names, I imparted your idea to the real problem and modified accordingly and it works. I will accept your answer here for someone who meets with similar problems.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
That’s a pretty big small typo. :-) Make sure you pre-allocate the required capacity in your sparse matrixHashMap
for maximum efficiency.
$endgroup$
– AJNeufeld
5 hours ago
$begingroup$
Hmm, even in the previous implementation which has exceeded time limit, increasing the capacity still fails. My current implementation can pass the time limit even without allocating capacity, but thanks for the reminder
$endgroup$
– Prashin Jeevaganth
4 hours ago
add a comment |
$begingroup$
Your data model is slowing down your code.
ArrayList<List<Object>> inputPairs = new ArrayList<>();
ArrayList<String> nameIterList = new ArrayList<>();//To store names in scanned order
HashMap<String, Integer> dupeCount = new HashMap<>();//To consider cases where there are people with same names
Calling ArrayList.add()
will add an item to the array list. If insufficient room exists in its storage area, the area reallocated double its previous size, and the information copied to the new storage area. With 50000 names, with an initial allocated space of 8 items, you will go through 13 reallocations of the inputPairs
and nameIterList
containers.
The HashMap
stores its information differently, but it will suffer from the same doubling of capacity steps, with an additional penalty of "rebinning" the contents into the proper bins.
All of this takes time, and all of this can all be avoided by pre-allocating your storage container sizes. You know what the limit is: 50000. Alternately, you can read in N
and then allocate properly sized storage containers.
int count = sc.nextInt();
ArrayList<List<Object>> inputPairs = new ArrayList<>(count);
ArrayList<String> nameIterList = new ArrayList<>(count);
HashMap<String, Integer> dupeCount = new HashMap<>(count*2);
A HashMap
will rebin by default at 75% capacity, so I've initialized it at double the required capacity, so it won't exceed the limit.
ArrayList<List<Object>>
may not be the worst storage structure to use, but it comes close. List.of(score,name)
should allocate a specialized, immutable two-member structure to use for the list, but you still have to go through the overhead of the List
interface to .get()
at the members. Worst, the score
has to be boxed from an efficient int
into a full blown Integer
object. This auto boxing takes both time and space. Worse, the additional object allocations will cause additional cache misses, slowing down the program. True, the Integer
objects will probably all be interned varieties, due to their restricted range, but it all adds up to your time-limit-exceeded issue.
List.of(score, name)
was used to avoid creating your own simple class:
class StudentRecord {
String name;
int score;
}
Instead of 3 objects (at least) per student, you only have two: the StudentRecord
and the name
. Access to the member fields is fast; no .get(int)
overhead. (But even this is overhead that you don't need!)
Checking for duplicate names, and creating fake names to avoid the duplicates is a time wasting operation. We can avoid it, with a smarter algorithm.
The better way
First: let's simplify the data down to the bare minimum...
int count = sc.nextInt();
String[] names = new String[count];
int[] score = new int[count];
... two parallel arrays, one containing the student names (in order), and one containing the scores (in order).
Let's jump to the middle...
int[] rank = new int[110];
You have 110 possible score values, each which corresponds to exactly one rank. If you have 5 students with a score of 109 and one student with a score of 108, then rank[109]
should contain 1
, and rank[108]
should contain 6
.
Jumping to the end...
for(int i=0; i<count; i++) {
System.out.printf("%s %dn", name[i], rank[score[i]]);
}
... prints out the student, looks up the rank corresponding to their score and prints that as well.
Creation of the rank[]
array
Since this is a programming challenge, I'll leave this up to you. There are several ways to do it. Good luck.
$endgroup$
Your data model is slowing down your code.
ArrayList<List<Object>> inputPairs = new ArrayList<>();
ArrayList<String> nameIterList = new ArrayList<>();//To store names in scanned order
HashMap<String, Integer> dupeCount = new HashMap<>();//To consider cases where there are people with same names
Calling ArrayList.add()
will add an item to the array list. If insufficient room exists in its storage area, the area reallocated double its previous size, and the information copied to the new storage area. With 50000 names, with an initial allocated space of 8 items, you will go through 13 reallocations of the inputPairs
and nameIterList
containers.
The HashMap
stores its information differently, but it will suffer from the same doubling of capacity steps, with an additional penalty of "rebinning" the contents into the proper bins.
All of this takes time, and all of this can all be avoided by pre-allocating your storage container sizes. You know what the limit is: 50000. Alternately, you can read in N
and then allocate properly sized storage containers.
int count = sc.nextInt();
ArrayList<List<Object>> inputPairs = new ArrayList<>(count);
ArrayList<String> nameIterList = new ArrayList<>(count);
HashMap<String, Integer> dupeCount = new HashMap<>(count*2);
A HashMap
will rebin by default at 75% capacity, so I've initialized it at double the required capacity, so it won't exceed the limit.
ArrayList<List<Object>>
may not be the worst storage structure to use, but it comes close. List.of(score,name)
should allocate a specialized, immutable two-member structure to use for the list, but you still have to go through the overhead of the List
interface to .get()
at the members. Worst, the score
has to be boxed from an efficient int
into a full blown Integer
object. This auto boxing takes both time and space. Worse, the additional object allocations will cause additional cache misses, slowing down the program. True, the Integer
objects will probably all be interned varieties, due to their restricted range, but it all adds up to your time-limit-exceeded issue.
List.of(score, name)
was used to avoid creating your own simple class:
class StudentRecord {
String name;
int score;
}
Instead of 3 objects (at least) per student, you only have two: the StudentRecord
and the name
. Access to the member fields is fast; no .get(int)
overhead. (But even this is overhead that you don't need!)
Checking for duplicate names, and creating fake names to avoid the duplicates is a time wasting operation. We can avoid it, with a smarter algorithm.
The better way
First: let's simplify the data down to the bare minimum...
int count = sc.nextInt();
String[] names = new String[count];
int[] score = new int[count];
... two parallel arrays, one containing the student names (in order), and one containing the scores (in order).
Let's jump to the middle...
int[] rank = new int[110];
You have 110 possible score values, each which corresponds to exactly one rank. If you have 5 students with a score of 109 and one student with a score of 108, then rank[109]
should contain 1
, and rank[108]
should contain 6
.
Jumping to the end...
for(int i=0; i<count; i++) {
System.out.printf("%s %dn", name[i], rank[score[i]]);
}
... prints out the student, looks up the rank corresponding to their score and prints that as well.
Creation of the rank[]
array
Since this is a programming challenge, I'll leave this up to you. There are several ways to do it. Good luck.
edited 12 hours ago
mdfst13
17.9k62157
17.9k62157
answered 13 hours ago
AJNeufeldAJNeufeld
6,1151520
6,1151520
$begingroup$
Hi, I like your ideas. Unfortunately, I have a small typo in my question that might cause a huge change to the solution. The range is 10^9 instead of 109, so I think the rank[] array now has to become a HashMap to handle a SparseMatrix representation.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
For this scenario caused by the typo, I do think your scenario can work. In particular, using an array to store names did better than using an encryption mechanism to make unique names, I imparted your idea to the real problem and modified accordingly and it works. I will accept your answer here for someone who meets with similar problems.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
That’s a pretty big small typo. :-) Make sure you pre-allocate the required capacity in your sparse matrixHashMap
for maximum efficiency.
$endgroup$
– AJNeufeld
5 hours ago
$begingroup$
Hmm, even in the previous implementation which has exceeded time limit, increasing the capacity still fails. My current implementation can pass the time limit even without allocating capacity, but thanks for the reminder
$endgroup$
– Prashin Jeevaganth
4 hours ago
add a comment |
$begingroup$
Hi, I like your ideas. Unfortunately, I have a small typo in my question that might cause a huge change to the solution. The range is 10^9 instead of 109, so I think the rank[] array now has to become a HashMap to handle a SparseMatrix representation.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
For this scenario caused by the typo, I do think your scenario can work. In particular, using an array to store names did better than using an encryption mechanism to make unique names, I imparted your idea to the real problem and modified accordingly and it works. I will accept your answer here for someone who meets with similar problems.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
That’s a pretty big small typo. :-) Make sure you pre-allocate the required capacity in your sparse matrixHashMap
for maximum efficiency.
$endgroup$
– AJNeufeld
5 hours ago
$begingroup$
Hmm, even in the previous implementation which has exceeded time limit, increasing the capacity still fails. My current implementation can pass the time limit even without allocating capacity, but thanks for the reminder
$endgroup$
– Prashin Jeevaganth
4 hours ago
$begingroup$
Hi, I like your ideas. Unfortunately, I have a small typo in my question that might cause a huge change to the solution. The range is 10^9 instead of 109, so I think the rank[] array now has to become a HashMap to handle a SparseMatrix representation.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
Hi, I like your ideas. Unfortunately, I have a small typo in my question that might cause a huge change to the solution. The range is 10^9 instead of 109, so I think the rank[] array now has to become a HashMap to handle a SparseMatrix representation.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
For this scenario caused by the typo, I do think your scenario can work. In particular, using an array to store names did better than using an encryption mechanism to make unique names, I imparted your idea to the real problem and modified accordingly and it works. I will accept your answer here for someone who meets with similar problems.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
For this scenario caused by the typo, I do think your scenario can work. In particular, using an array to store names did better than using an encryption mechanism to make unique names, I imparted your idea to the real problem and modified accordingly and it works. I will accept your answer here for someone who meets with similar problems.
$endgroup$
– Prashin Jeevaganth
10 hours ago
$begingroup$
That’s a pretty big small typo. :-) Make sure you pre-allocate the required capacity in your sparse matrix
HashMap
for maximum efficiency.$endgroup$
– AJNeufeld
5 hours ago
$begingroup$
That’s a pretty big small typo. :-) Make sure you pre-allocate the required capacity in your sparse matrix
HashMap
for maximum efficiency.$endgroup$
– AJNeufeld
5 hours ago
$begingroup$
Hmm, even in the previous implementation which has exceeded time limit, increasing the capacity still fails. My current implementation can pass the time limit even without allocating capacity, but thanks for the reminder
$endgroup$
– Prashin Jeevaganth
4 hours ago
$begingroup$
Hmm, even in the previous implementation which has exceeded time limit, increasing the capacity still fails. My current implementation can pass the time limit even without allocating capacity, but thanks for the reminder
$endgroup$
– Prashin Jeevaganth
4 hours ago
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215393%2franking-score-system%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown